diff --git a/config/markets.ts b/config/markets.ts index b6c248bf8..df7bed744 100644 --- a/config/markets.ts +++ b/config/markets.ts @@ -23,6 +23,17 @@ export type BaseMarketConfig = { maxLongTokenPoolAmount: BigNumberish; maxShortTokenPoolAmount: BigNumberish; + // note that maxCollateralSum is used to fill maxLongCollateralSum and maxShortCollateralSum + // these values indicate the max sum of collaterals for a market + // maxLongCollateralSum and maxShortCollateralSum is duplicated for long and short positions + // e.g. if maxLongCollateralSum is 1000 tokens, then maxLongCollateralSum for longs + // and maxLongCollateralSum for shorts would both be 1000 tokens + // to make the configuration more intuitive, the maxLongCollateralSum and maxShortCollateralSum is divided by two + // in updateMarketConfigUtils + maxCollateralSum: BigNumberish; + maxLongCollateralSum?: BigNumberish; + maxShortCollateralSum?: BigNumberish; + maxPoolUsdForDeposit?: BigNumberish; maxLongTokenPoolUsdForDeposit?: BigNumberish; maxShortTokenPoolUsdForDeposit?: BigNumberish; @@ -260,6 +271,12 @@ const borrowingRateConfig_HighMax_WithHigherBase: BorrowingRateConfig = { aboveOptimalUsageBorrowingFactor: percentageToFloat("130%").div(SECONDS_PER_YEAR), }; +const borrowingRateConfig_LowerMax_WithHigherOptimal: BorrowingRateConfig = { + optimalUsageFactor: percentageToFloat("85%"), + baseBorrowingFactor: percentageToFloat("45%").div(SECONDS_PER_YEAR), + aboveOptimalUsageBorrowingFactor: percentageToFloat("90%").div(SECONDS_PER_YEAR), +}; + const baseMarketConfig: Partial = { minCollateralFactor: percentageToFloat("1%"), // 1% minCollateralFactorForLiquidation: percentageToFloat("1%"), // 1% @@ -297,6 +314,7 @@ const baseMarketConfig: Partial = { swapImpactExponentFactor: exponentToFloat("2e0"), // 2 minCollateralUsd: decimalToFloat(1, 0), // 1 USD + maxCollateralSum: expandDecimals(10_000_000_000_000, 18), // 10 trillion with 18 decimals // factor in open interest reserve factor 80% borrowingFactor: decimalToFloat(625, 11), // 0.00000000625 * 80% = 0.000000005, 0.0000005% / second, 15.77% per year if the pool is 100% utilized @@ -397,6 +415,8 @@ const hardhatBaseMarketConfig: Partial = { maxLongTokenPoolAmount: expandDecimals(1_000_000_000, 18), maxShortTokenPoolAmount: expandDecimals(1_000_000_000, 18), + maxCollateralSum: expandDecimals(10_000_000_000_000, 18), // 10 trillion with 18 decimals + maxPoolUsdForDeposit: decimalToFloat(1_000_000_000_000_000), maxOpenInterest: decimalToFloat(1_000_000_000), @@ -458,7 +478,7 @@ const config: { ...baseMarketConfig, ...fundingRateConfig_Low, - ...borrowingRateConfig_LowMax_WithLowerBase, + ...borrowingRateConfig_LowerMax_WithHigherOptimal, reserveFactor: percentageToFloat("350%"), openInterestReserveFactor: percentageToFloat("345%"), @@ -555,7 +575,7 @@ const config: { ...baseMarketConfig, ...fundingRateConfig_Low, - ...borrowingRateConfig_LowMax_WithLowerBase, + ...borrowingRateConfig_LowerMax_WithHigherOptimal, reserveFactor: percentageToFloat("275%"), openInterestReserveFactor: percentageToFloat("270%"), @@ -956,7 +976,7 @@ const config: { ...baseMarketConfig, ...fundingRateConfig_Default, - ...borrowingRateConfig_LowMax_WithLowerBase, + ...borrowingRateConfig_LowerMax_WithHigherOptimal, maxLongTokenPoolAmount: expandDecimals(110_000, 9), maxShortTokenPoolAmount: expandDecimals(20_000_000, 6), @@ -1128,7 +1148,7 @@ const config: { ...baseMarketConfig, ...fundingRateConfig_Default, - ...borrowingRateConfig_LowMax_WithLowerBase, + ...borrowingRateConfig_LowerMax_WithHigherOptimal, reserveFactor: percentageToFloat("305%"), openInterestReserveFactor: percentageToFloat("300%"), @@ -3744,11 +3764,11 @@ const config: { openInterestReserveFactor: percentageToFloat("100%"), maxPnlFactorForTraders: percentageToFloat("50%"), - maxOpenInterest: decimalToFloat(500_000), - maxPoolUsdForDeposit: decimalToFloat(750_000), + maxOpenInterest: decimalToFloat(600_000), + maxPoolUsdForDeposit: decimalToFloat(900_000), - maxLongTokenPoolAmount: expandDecimals(220, 18), // ~1M USD (2x max open interest) - maxShortTokenPoolAmount: expandDecimals(1_000_000, 6), // ~1M USD (2x max open interest) + maxLongTokenPoolAmount: expandDecimals(270, 18), // ~1.08M USD (2x max open interest) + maxShortTokenPoolAmount: expandDecimals(1_080_000, 6), // ~1.08M USD (2x max open interest) }, { tokens: { indexToken: "WLFI", longToken: "WETH", shortToken: "USDC" }, @@ -3907,11 +3927,11 @@ const config: { openInterestReserveFactor: percentageToFloat("100%"), maxPnlFactorForTraders: percentageToFloat("90%"), - maxOpenInterest: decimalToFloat(1_000_000), - maxPoolUsdForDeposit: decimalToFloat(1_500_000), + maxOpenInterest: decimalToFloat(1_500_000), + maxPoolUsdForDeposit: decimalToFloat(2_250_000), - maxLongTokenPoolAmount: expandDecimals(16, 8), // ~2M USD (2x max open interest) - maxShortTokenPoolAmount: expandDecimals(2_000_000, 6), // ~2M USD (2x max open interest) + maxLongTokenPoolAmount: expandDecimals(25, 8), // ~2.7M USD (2x max open interest) + maxShortTokenPoolAmount: expandDecimals(2_700_000, 6), // ~2.7M USD (2x max open interest) }, { tokens: { indexToken: "0G", longToken: "WBTC.e", shortToken: "USDC" }, @@ -4507,6 +4527,61 @@ const config: { atomicSwapFeeFactor: percentageToFloat("0.5%"), }, + { + tokens: { indexToken: "XAUt0", longToken: "XAUt0", shortToken: "XAUt0" }, + virtualTokenIdForIndexToken: hashString("PERP:XAUt0/USD"), + virtualMarketId: hashString("SPOT:XAUt0/USD"), + + ...singleTokenMarketConfig, + ...fundingRateConfig_Low, + ...borrowingRateConfig_LowMax_WithLowerBase, + + negativePositionImpactFactor: exponentToFloat("9.29e-9"), + positivePositionImpactFactor: exponentToFloat("7.74e-9"), + + minCollateralFactor: percentageToFloat("0.5%"), // 200x leverage + minCollateralFactorForLiquidation: percentageToFloat("0.5%"), // 200x leverage + minCollateralFactorForOpenInterestMultiplier: exponentToFloat("2.78e-9"), + + reserveFactor: percentageToFloat("105%"), + openInterestReserveFactor: percentageToFloat("100%"), + maxPnlFactorForTraders: percentageToFloat("90%"), + + maxOpenInterest: decimalToFloat(2_000_000), + maxPoolUsdForDeposit: decimalToFloat(3_000_000), + + maxLongTokenPoolAmount: expandDecimals(940, 6), // ~4M USD (2x max open interest) + maxShortTokenPoolAmount: expandDecimals(940, 6), // ~4M USD (2x max open interest) + }, + { + tokens: { indexToken: "XAUt0", longToken: "XAUt0", shortToken: "USDT" }, + virtualTokenIdForIndexToken: hashString("PERP:XAUt0/USD"), + virtualMarketId: hashString("SPOT:XAUt0/USDT"), + + ...baseMarketConfig, + ...fundingRateConfig_Low, + ...borrowingRateConfig_LowMax_WithLowerBase, + + negativePositionImpactFactor: exponentToFloat("9.29e-9"), + positivePositionImpactFactor: exponentToFloat("7.74e-9"), + + negativeSwapImpactFactor: exponentToFloat("3.5e-9"), + positiveSwapImpactFactor: exponentToFloat("1.75e-9"), + + minCollateralFactor: percentageToFloat("0.5%"), + minCollateralFactorForLiquidation: percentageToFloat("0.5%"), + minCollateralFactorForOpenInterestMultiplier: exponentToFloat("2.14e-9"), + + reserveFactor: percentageToFloat("135%"), + openInterestReserveFactor: percentageToFloat("130%"), + maxPnlFactorForTraders: percentageToFloat("90%"), + + maxOpenInterest: decimalToFloat(2_000_000), + maxPoolUsdForDeposit: decimalToFloat(3_000_000), + + maxLongTokenPoolAmount: expandDecimals(940, 6), // ~4M USD (2x max open interest) + maxShortTokenPoolAmount: expandDecimals(4_000_000, 6), // ~4M USD (2x max open interest) + }, ], arbitrumSepolia: [ { @@ -5160,6 +5235,8 @@ export default async function (hre: HardhatRuntimeEnvironment) { "maxShortTokenPoolUsdForDeposit" ); + fillLongShortValues(market, "maxCollateralSum", "maxLongCollateralSum", "maxShortCollateralSum"); + fillLongShortValues(market, "maxOpenInterest", "maxOpenInterestForLongs", "maxOpenInterestForShorts"); fillLongShortValues( diff --git a/config/roleConfigs/arbitrum.ts b/config/roleConfigs/arbitrum.ts new file mode 100644 index 000000000..2e922f30c --- /dev/null +++ b/config/roleConfigs/arbitrum.ts @@ -0,0 +1,111 @@ +export function getRoles({ + syntheticKeepers, + chainlinkKeepers, + gelatoKeepers, + claimAdmins, + generalConfigKeepers, + fundDistributors, +}) { + return { + ADL_KEEPER: syntheticKeepers.mainnet, + FROZEN_ORDER_KEEPER: syntheticKeepers.mainnet, + LIQUIDATION_KEEPER: syntheticKeepers.mainnet, + ORDER_KEEPER: { ...syntheticKeepers.mainnet, ...chainlinkKeepers.arbitrum, ...gelatoKeepers.arbitrum }, + LIMITED_CONFIG_KEEPER: syntheticKeepers.mainnet, + CLAIM_ADMIN: { + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + ...claimAdmins.mainnet, + ...generalConfigKeepers.mainnet, + }, + CONTRIBUTOR_KEEPER: { + "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b": true, // contributor_keeper_1 + }, + CONTRIBUTOR_DISTRIBUTOR: { + ...generalConfigKeepers.mainnet, + ...fundDistributors.mainnet, + }, + CONFIG_KEEPER: { + "0x4b6ACC5b2db1757bD49408FeE92e32D39608B5d9": true, // multisig_1 + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + "0xd41e09434CDFe20ceA9411f55D86dDb314b6Af94": true, // ConfigSyncer + ...generalConfigKeepers.mainnet, + }, + FEE_KEEPER: { + "0x43CE1d475e06c65DD879f4ec644B8e0E10ff2b6D": true, // fee_keeper_1 + }, + // FEE_DISTRIBUTION_KEEPER: generalConfigKeepers.mainnet, + MARKET_KEEPER: { + ...generalConfigKeepers.mainnet, + }, + TIMELOCK_ADMIN: { + "0x35ea3066F90Db13e737BBd41f1ED7B4bfF8323b3": true, // timelock_admin_1 + "0xE014cbD60A793901546178E1c16ad9132C927483": true, // timelock_admin_2 + "0x4b6ACC5b2db1757bD49408FeE92e32D39608B5d9": true, // multisig_1 + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + }, + TIMELOCK_MULTISIG: { + "0x4b6ACC5b2db1757bD49408FeE92e32D39608B5d9": true, // multisig_1 + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + }, + GOV_TOKEN_CONTROLLER: { + "0x5E4766F932ce00aA4a1A82d3Da85adf15C5694A1": true, // RewardRouterV2 + }, + CONTROLLER: { + "0xf5F30B10141E1F63FC11eD772931A8294a591996": true, // MarketFactory + "0xdaFa7Deb67805d7498Aa926002bB2d713D1d9256": true, // GlvFactory + "0xA8AF9B86fC47deAde1bc66B12673706615E2B011": true, // OracleStore + "0x7EB417637a3E6d1C19E6d69158c47610b7a5d9B3": true, // FeeHandler + + "0x1d3dbe2F913dcA27E943b2837A4Cdad6653B02E2": true, // Config + "0xd41e09434CDFe20ceA9411f55D86dDb314b6Af94": true, // ConfigSyncer + "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f": true, // ConfigTimelockController + "0x4729D9f61c0159F5e02D2C2e5937B3225e55442C": true, // ContributorHandler + "0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1": true, // TimelockConfig + "0x7F01614cA5198Ec979B1aAd1DAF0DE7e0a215BDF": true, // Oracle + "0xb8fc96d7a413C462F611A7aC0C912c2FE26EAbC4": true, // FeeHandler Oracle + "0x87d66368cD08a7Ca42252f5ab44B2fb6d1Fb8d15": true, // ExchangeRouter + "0x5b9A353F18d543B9F8a57B2AE50a4FBc80033EC1": true, // SubaccountRouter + "0x10Fa5Bd343373101654E896B43Ca38Fd8f3789F9": true, // GlvRouter + "0x0C08518C41755C6907135266dCCf09d51aE53CC4": true, // GelatoRelayRouter + "0xA1D94802EcD642051B677dBF37c8E78ce6dd3784": true, // SubaccountGelatoRelayRouter + "0x04315E233C1c6FfA61080B76E29d5e8a1f7B4A35": true, // OrderHandler + "0x1DAa9A375132a3cDe9133B0a5DA67B57Ef21d102": true, // IncreaseOrderExecutor + "0x3F4ee93723C2F14eeC5a44a2Cb66edA006A171fd": true, // DecreaseOrderExecutor + "0x455D555350D5CcCD1E3Eb3D563B411Ef24697050": true, // SwapOrderExecutor + "0x563E8cDB5Ba929039c2Bb693B78CE12dC0AAfaDa": true, // DepositHandler + "0x1EC018d2b6ACCA20a0bEDb86450b7E27D1D8355B": true, // WithdrawalHandler + "0xDd20D75f92bF27e17d86D74424ce7435843E8df0": true, // AdlHandler + "0xdFc557EdF817bCd69F3b82d54f6338ecad2667CA": true, // LiquidationHandler + "0x763fD06BaF6bBcE1A06ab94C6dFd13813E517938": true, // ShiftHandler + "0xBB4C47CDfb90e281cAAE873c9531A25eBe2eD343": true, // GlvDepositHandler + "0x7A74946892569Fd488012D015436a5a9cBf37BEf": true, // GlvWithdrawalHandler + "0x632b763B31f9A1cB28c4f93925A591Cd34073AD6": true, // GlvShiftHandler + "0xDb2AB9566732710d02b23325F79A8832118b97c5": true, // SwapHandler + "0x28f1F4AA95F49FAB62464536A269437B13d48976": true, // ClaimHandler + "0x7129Ea01F0826c705d6F7ab01Cf3C06bb83E9397": true, // LayerZeroProvider + "0x2A7244EE5373D2F161cE99F0D144c12860D651Af": true, // MultichainClaimsRouter + "0xFdaFa6fbd4B480017FD37205Cb3A24AE93823956": true, // MultichainGlvRouter + "0xF53e30CE07f148fdE6e531Be7dC0b6ad670E8C6e": true, // MultichainGmRouter + "0x3c796504d47013Ea0552CCa57373B59DF03D34a0": true, // MultichainOrderRouter + "0x99CD306B777C5aAb842bA65e4f7FF0554ECDe808": true, // MultichainSubaccountRouter + "0xC1D1354A948bf717d6d873e5c0bE614359AF954D": true, // MultichainTransferRouter + }, + ROUTER_PLUGIN: { + "0x87d66368cD08a7Ca42252f5ab44B2fb6d1Fb8d15": true, // ExchangeRouter + "0x5b9A353F18d543B9F8a57B2AE50a4FBc80033EC1": true, // SubaccountRouter + "0x10Fa5Bd343373101654E896B43Ca38Fd8f3789F9": true, // GlvRouter + "0x0C08518C41755C6907135266dCCf09d51aE53CC4": true, // GelatoRelayRouter + "0xA1D94802EcD642051B677dBF37c8E78ce6dd3784": true, // SubaccountGelatoRelayRouter + "0xFdaFa6fbd4B480017FD37205Cb3A24AE93823956": true, // MultichainGlvRouter + "0xF53e30CE07f148fdE6e531Be7dC0b6ad670E8C6e": true, // MultichainGmRouter + "0x3c796504d47013Ea0552CCa57373B59DF03D34a0": true, // MultichainOrderRouter + "0x99CD306B777C5aAb842bA65e4f7FF0554ECDe808": true, // MultichainSubaccountRouter + "0xC1D1354A948bf717d6d873e5c0bE614359AF954D": true, // MultichainTransferRouter + }, + ROLE_ADMIN: { + "0x4bd1cdAab4254fC43ef6424653cA2375b4C94C0E": true, // GMX DAO + "0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1": true, // TimelockConfig + "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f": true, // ConfigTimelockController + }, + }; +} diff --git a/config/roleConfigs/avalanche.ts b/config/roleConfigs/avalanche.ts new file mode 100644 index 000000000..6f973c7e9 --- /dev/null +++ b/config/roleConfigs/avalanche.ts @@ -0,0 +1,95 @@ +export function getRoles({ syntheticKeepers, generalConfigKeepers, claimAdmins }) { + return { + ADL_KEEPER: syntheticKeepers.mainnet, + FROZEN_ORDER_KEEPER: syntheticKeepers.mainnet, + LIQUIDATION_KEEPER: syntheticKeepers.mainnet, + ORDER_KEEPER: syntheticKeepers.mainnet, + LIMITED_CONFIG_KEEPER: syntheticKeepers.mainnet, + CLAIM_ADMIN: { + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + ...claimAdmins.mainnet, + ...generalConfigKeepers.mainnet, + }, + CONFIG_KEEPER: { + "0x15F9eBC71c539926B8f652a534d29B4Af57CaD55": true, // multisig_1 + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + "0x372aaDF1921c6f92346a4D5E9E5186bd00fF0562": true, // ConfigSyncer + ...generalConfigKeepers.mainnet, + }, + FEE_KEEPER: { + "0x43CE1d475e06c65DD879f4ec644B8e0E10ff2b6D": true, // fee_keeper_1 + }, + // FEE_DISTRIBUTION_KEEPER: generalConfigKeepers.mainnet, + MARKET_KEEPER: { + ...generalConfigKeepers.mainnet, + }, + TIMELOCK_ADMIN: { + "0x35ea3066F90Db13e737BBd41f1ED7B4bfF8323b3": true, // timelock_admin_1 + "0xE014cbD60A793901546178E1c16ad9132C927483": true, // timelock_admin_2 + "0x15F9eBC71c539926B8f652a534d29B4Af57CaD55": true, // multisig_1 + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + }, + TIMELOCK_MULTISIG: { + "0x15F9eBC71c539926B8f652a534d29B4Af57CaD55": true, // multisig_1 + "0x8D1d2e24eC641eDC6a1ebe0F3aE7af0EBC573e0D": true, // security_multisig_1 + }, + GOV_TOKEN_CONTROLLER: { + "0x091eD806490Cc58Fd514441499e58984cCce0630": true, // RewardRouterV2_2 + }, + CONTROLLER: { + "0xc57C155FacCd93F62546F329D1483E0E5b9C1241": true, // MarketFactory + "0x5d6B84086DA6d4B0b6C0dF7E02f8a6A039226530": true, // GlvFactory + "0xA6aC2e08C6d6bbD9B237e0DaaEcd7577996f4e84": true, // OracleStore + "0x1A3A103F9F536a0456C9b205152A3ac2b3c54490": true, // FeeHandler + + "0xA421Fa4581b37CAE2E43502D205460a57B7D7a4b": true, // Config + "0x372aaDF1921c6f92346a4D5E9E5186bd00fF0562": true, // ConfigSyncer + "0xB8cAEF9245cbd9064a50830f8330B0D3a5d0D206": true, // ConfigTimelockController + "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f": true, // TimelockConfig + "0xE1d5a068c5b75E0c7Ea1A9Fe8EA056f9356C6fFD": true, // Oracle + "0xAd7a7568F500F65AEA3D9417A210CBc5dcD7b273": true, // FeeHandler Oracle + "0xF0864BE1C39C0AB28a8f1918BC8321beF8F7C317": true, // ExchangeRouter + "0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3": true, // SubaccountRouter + "0x4729D9f61c0159F5e02D2C2e5937B3225e55442C": true, // GlvRouter + "0xa61f92ab63cc5C3d60574d40A6e73861c37aaC95": true, // GelatoRelayRouter + "0x58b09FD12863218F2ca156808C2Ae48aaCD0c072": true, // SubaccountGelatoRelayRouter + "0xDd20D75f92bF27e17d86D74424ce7435843E8df0": true, // OrderHandler + "0x24F52966Fc663b3e206f0DCbD40b6FF2df567880": true, // IncreaseOrderExecutor + "0x74bfc9c1E496D96bbAF87A8231aAD1c79DDbf7bA": true, // DecreaseOrderExecutor + "0x459058505A7c7252efE93aa69D03F6198601DA9e": true, // SwapOrderExecutor + "0x640dFe87059fEe3Ad59132ABb858191D7Fa5B219": true, // DepositHandler + "0x87d66368cD08a7Ca42252f5ab44B2fb6d1Fb8d15": true, // WithdrawalHandler + "0x2954C692cc26EF139f3B01435cd901A39a8cA830": true, // AdlHandler + "0x2e5D10A48C00cFcc6A31af873118d739323Ff71B": true, // LiquidationHandler + "0x0C08518C41755C6907135266dCCf09d51aE53CC4": true, // ShiftHandler + "0x632b763B31f9A1cB28c4f93925A591Cd34073AD6": true, // GlvDepositHandler + "0xdFc557EdF817bCd69F3b82d54f6338ecad2667CA": true, // GlvWithdrawalHandler + "0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8": true, // GlvShiftHandler + "0x0AF4d7c87339d3A4b40233439A4aBE13d97007f9": true, // SwapHandler + "0x7FfedCAC2eCb2C29dDc027B60D6F8107295Ff2eA": true, // ClaimHandler + "0xA1D94802EcD642051B677dBF37c8E78ce6dd3784": true, // LayerZeroProvider + "0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB": true, // MultichainClaimsRouter + "0x2A7244EE5373D2F161cE99F0D144c12860D651Af": true, // MultichainGlvRouter + "0x10Fa5Bd343373101654E896B43Ca38Fd8f3789F9": true, // MultichainGmRouter + "0x99CD306B777C5aAb842bA65e4f7FF0554ECDe808": true, // MultichainOrderRouter + "0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4": true, // MultichainSubaccountRouter + "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621": true, // MultichainTransferRouter + }, + ROUTER_PLUGIN: { + "0xF0864BE1C39C0AB28a8f1918BC8321beF8F7C317": true, // ExchangeRouter + "0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3": true, // SubaccountRouter + "0x4729D9f61c0159F5e02D2C2e5937B3225e55442C": true, // GlvRouter + "0xa61f92ab63cc5C3d60574d40A6e73861c37aaC95": true, // GelatoRelayRouter + "0x58b09FD12863218F2ca156808C2Ae48aaCD0c072": true, // SubaccountGelatoRelayRouter + "0x2A7244EE5373D2F161cE99F0D144c12860D651Af": true, // MultichainGlvRouter + "0x10Fa5Bd343373101654E896B43Ca38Fd8f3789F9": true, // MultichainGmRouter + "0x99CD306B777C5aAb842bA65e4f7FF0554ECDe808": true, // MultichainOrderRouter + "0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4": true, // MultichainSubaccountRouter + "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621": true, // MultichainTransferRouter + }, + ROLE_ADMIN: { + "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f": true, // TimelockConfig + "0xB8cAEF9245cbd9064a50830f8330B0D3a5d0D206": true, // ConfigTimelockController + }, + }; +} diff --git a/config/roleConfigs/botanix.ts b/config/roleConfigs/botanix.ts new file mode 100644 index 000000000..b965f4872 --- /dev/null +++ b/config/roleConfigs/botanix.ts @@ -0,0 +1,85 @@ +export function getRoles({ syntheticKeepers, generalConfigKeepers, claimAdmins }) { + return { + ADL_KEEPER: syntheticKeepers.mainnet, + FROZEN_ORDER_KEEPER: syntheticKeepers.mainnet, + LIQUIDATION_KEEPER: syntheticKeepers.mainnet, + ORDER_KEEPER: syntheticKeepers.mainnet, + LIMITED_CONFIG_KEEPER: syntheticKeepers.mainnet, + CLAIM_ADMIN: { + "0x656fa39BdB5984b477FA6aB443195D72D1Accc1c": true, // security_multisig_botanix + ...claimAdmins.mainnet, + ...generalConfigKeepers.mainnet, + }, + CONFIG_KEEPER: { + "0x656fa39BdB5984b477FA6aB443195D72D1Accc1c": true, // security_multisig_botanix + ...generalConfigKeepers.mainnet, + }, + FEE_KEEPER: { + "0x43CE1d475e06c65DD879f4ec644B8e0E10ff2b6D": true, // fee_keeper_1 + }, + MARKET_KEEPER: { + ...generalConfigKeepers.mainnet, + }, + TIMELOCK_ADMIN: { + "0x35ea3066F90Db13e737BBd41f1ED7B4bfF8323b3": true, // timelock_admin_1 + "0xE014cbD60A793901546178E1c16ad9132C927483": true, // timelock_admin_2 + "0x656fa39BdB5984b477FA6aB443195D72D1Accc1c": true, // security_multisig_botanix + }, + TIMELOCK_MULTISIG: { + "0x656fa39BdB5984b477FA6aB443195D72D1Accc1c": true, // multisig_1 + }, + GOV_TOKEN_CONTROLLER: {}, + CONTROLLER: { + "0xcb7656751B0f8aFCBe15D135D7aC58727DE06768": true, // MarketFactory + "0x3e04e6b37B23969F3Ca1c2aAc8568322bd90BA90": true, // GlvFactory + "0xfFC63573B55B39b75b1e44e54C308e44505E0D28": true, // OracleStore + + "0xB65F74fBa4E2A5db9302b33FB4459AbBC593370f": true, // Config + "0xB4085c68765bEAf991D3e4EEbC48427EDECBA778": true, // ConfigTimelockController + "0xc7D8E3561f1247EBDa491bA5f042699C2807C33C": true, // TimelockConfig + "0x40d680E41FC4Bf973F0EA664981f6359195a6383": true, // Oracle + "0x72fa3978E2E330C7B2debc23CB676A3ae63333F6": true, // ExchangeRouter + "0x11E590f6092D557bF71BaDEd50D81521674F8275": true, // SubaccountRouter + "0x348Eca94e7c6F35430aF1cAccE27C29E9Bef9ae3": true, // GlvRouter + "0x7f8eF83C92B48a4B5B954A24D98a6cD0Ed4D160a": true, // GelatoRelayRouter + "0xfbb9C41046E27405224a911f44602C3667f9D8f6": true, // SubaccountGelatoRelayRouter + "0xb92b643950f57d0aCCf79950d6436557c869c5F8": true, // OrderHandler + "0x4f97e3589aE036e95F7ec091f0B373576987A01d": true, // IncreaseOrderExecutor + "0xa3c7575c56DA54b6e04DB4e4a9eE28bD670e2ba9": true, // DecreaseOrderExecutor + "0x61B6ae0dd5f5F4fC79D94f118fd4ab2864f0eEf9": true, // SwapOrderExecutor + "0x17b80086D9b00f1eE4C245409b03383e9cee2A7E": true, // DepositHandler + "0x5104257d85df1aF13b267e161E289847dd8950C6": true, // WithdrawalHandler + "0xb5fbb36853a136DD5DFf9314c48dF6AC0278dc72": true, // AdlHandler + "0x6EBfF697250ae729AD0752f5Ca6CE98Bc62D4213": true, // LiquidationHandler + "0x0eaAbf9234333FF67CB8FDBc3Dafe13F7E7c2B71": true, // ShiftHandler + "0x80EDF3eA04D30FEc027C4B397ab034D7FA98b894": true, // GlvDepositHandler + "0x090FA7eb8B4647DaDbEA315E68f8f88e8E62Bd54": true, // GlvWithdrawalHandler + "0x8622db0e78671e3C5696AF763D6679dE5c18890c": true, // GlvShiftHandler + "0xf6BE2059947535c12615FDb642583A3547550eb7": true, // SwapHandler + "0x3cA0F3AD78A9d0b2a0c060fE86D1141118A285c4": true, // ClaimHandler + "0x61af99b07995cb7Ee8c2FACF6D8fb6042FeAA0d9": true, // LayerZeroProvider + "0x790Ee987b9B253374d700b07F16347a7d4C4ff2e": true, // MultichainClaimsRouter + "0xEE027373517a6D96Fe62f70E9A0A395cB5a39Eee": true, // MultichainGlvRouter + "0x4ef8394CD5DD7E3EE6D30824689eF461783a3360": true, // MultichainGmRouter + "0x5c5DBbcDf420B5d81d4FfDBa5b26Eb24E6E60d52": true, // MultichainOrderRouter + "0xd3B6E962f135634C43415d57A28E688Fb4f15A58": true, // MultichainSubaccountRouter + "0x901f26a57edCe65Ef3FBcCD260433De9B2279852": true, // MultichainTransferRouter + }, + ROUTER_PLUGIN: { + "0x72fa3978E2E330C7B2debc23CB676A3ae63333F6": true, // ExchangeRouter + "0x11E590f6092D557bF71BaDEd50D81521674F8275": true, // SubaccountRouter + "0x348Eca94e7c6F35430aF1cAccE27C29E9Bef9ae3": true, // GlvRouter + "0x7f8eF83C92B48a4B5B954A24D98a6cD0Ed4D160a": true, // GelatoRelayRouter + "0xfbb9C41046E27405224a911f44602C3667f9D8f6": true, // SubaccountGelatoRelayRouter + "0xEE027373517a6D96Fe62f70E9A0A395cB5a39Eee": true, // MultichainGlvRouter + "0x4ef8394CD5DD7E3EE6D30824689eF461783a3360": true, // MultichainGmRouter + "0x5c5DBbcDf420B5d81d4FfDBa5b26Eb24E6E60d52": true, // MultichainOrderRouter + "0xd3B6E962f135634C43415d57A28E688Fb4f15A58": true, // MultichainSubaccountRouter + "0x901f26a57edCe65Ef3FBcCD260433De9B2279852": true, // MultichainTransferRouter + }, + ROLE_ADMIN: { + "0xc7D8E3561f1247EBDa491bA5f042699C2807C33C": true, // TimelockConfig + "0xB4085c68765bEAf991D3e4EEbC48427EDECBA778": true, // ConfigTimelockController + }, + }; +} diff --git a/config/roleConfigs/index.ts b/config/roleConfigs/index.ts new file mode 100644 index 000000000..788c3816d --- /dev/null +++ b/config/roleConfigs/index.ts @@ -0,0 +1,3 @@ +export { getRoles as arbitrum } from "./arbitrum"; +export { getRoles as avalanche } from "./avalanche"; +export { getRoles as botanix } from "./botanix"; diff --git a/config/roles.ts b/config/roles.ts index 98297f0f2..12e8db0b9 100644 --- a/config/roles.ts +++ b/config/roles.ts @@ -1,4 +1,5 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; +import * as roleConfigs from "./roleConfigs"; export type RolesConfig = { roles: { @@ -16,6 +17,7 @@ const requiredRolesForContracts = { "Config", "ConfigSyncer", "ConfigTimelockController", + "ContributorHandler", "MarketFactory", "GlvFactory", @@ -130,6 +132,20 @@ export default async function (hre: HardhatRuntimeEnvironment): Promise 0) { validateOpenInterest( @@ -1178,9 +1181,11 @@ library MarketUtils { DataStore dataStore, EventEmitter eventEmitter, address market, + address indexToken, address collateralToken, bool isLong, - int256 delta + int256 delta, + bool useOpenInterestInTokens ) internal returns (uint256) { uint256 nextValue = dataStore.applyDeltaToUint( Keys.openInterestInTokensKey(market, collateralToken, isLong), @@ -1188,6 +1193,23 @@ library MarketUtils { "Invalid state: negative open interest in tokens" ); + // if the open interest for longs is increased then tokens were virtually bought from the pool + // so the virtual inventory should be decreased + // if the open interest for longs is decreased then tokens were virtually sold to the pool + // so the virtual inventory should be increased + // if the open interest for shorts is increased then tokens were virtually sold to the pool + // so the virtual inventory should be increased + // if the open interest for shorts is decreased then tokens were virtually bought from the pool + // so the virtual inventory should be decreased + if (useOpenInterestInTokens) { + applyDeltaToVirtualInventoryForPositionsInTokens( + dataStore, + eventEmitter, + indexToken, + isLong ? -delta : delta + ); + } + MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue); return nextValue; @@ -1214,6 +1236,11 @@ library MarketUtils { "Invalid state: negative collateralSum" ); + uint256 maxValue = dataStore.getUint(Keys.maxCollateralSumKey(market, collateralToken, isLong)); + if (nextValue > maxValue) { + revert Errors.MaxCollateralSumExceeded(nextValue, maxValue); + } + MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue); return nextValue; @@ -1330,11 +1357,17 @@ library MarketUtils { uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); - // get the open interest values by long / short and by collateral used - cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor); - cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor); - cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor); - cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor); + cache.openInterest.long.longToken = getOpenInterest({ dataStore: dataStore, market: market.marketToken, divisor: divisor, + isLong: true, collateralToken: market.longToken }); + + cache.openInterest.long.shortToken = getOpenInterest({ dataStore: dataStore, market: market.marketToken, divisor: divisor, + isLong: true, collateralToken: market.shortToken }); + + cache.openInterest.short.longToken = getOpenInterest({ dataStore: dataStore, market: market.marketToken, divisor: divisor, + isLong: false, collateralToken: market.longToken }); + + cache.openInterest.short.shortToken = getOpenInterest({ dataStore: dataStore, market: market.marketToken, divisor: divisor, + isLong: false, collateralToken: market.shortToken }); // sum the open interest values to get the total long and short open interest values cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken; @@ -1353,9 +1386,8 @@ library MarketUtils { (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond( dataStore, - market.marketToken, - cache.longOpenInterest, - cache.shortOpenInterest, + market, + prices.indexTokenPrice.midPrice(), cache.durationInSeconds ); @@ -1492,18 +1524,35 @@ library MarketUtils { // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond function getNextFundingFactorPerSecond( DataStore dataStore, - address market, - uint256 longOpenInterest, - uint256 shortOpenInterest, + Market.Props memory market, + uint256 indexTokenPrice, uint256 durationInSeconds ) internal view returns (uint256, bool, int256) { GetNextFundingFactorPerSecondCache memory cache; + bool useOpenInterestInTokens = dataStore.getBool(Keys.USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE); + + uint256 longOpenInterest = getOpenInterestForBalance({ + dataStore: dataStore, + market: market, + useOpenInterestInTokens: useOpenInterestInTokens, + indexTokenPrice: indexTokenPrice, + isLong: true + }); + + uint256 shortOpenInterest = getOpenInterestForBalance({ + dataStore: dataStore, + market: market, + useOpenInterestInTokens: useOpenInterestInTokens, + indexTokenPrice: indexTokenPrice, + isLong: false + }); + cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest); cache.totalOpenInterest = longOpenInterest + shortOpenInterest; FundingConfigCache memory configCache; - configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market)); + configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market.marketToken)); // if the open interest difference is zero and adaptive funding // is not enabled, then return zero as the funding factor @@ -1515,14 +1564,14 @@ library MarketUtils { revert Errors.UnableToGetFundingFactorEmptyOpenInterest(); } - cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market); + cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market.marketToken); cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor); cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest); if (configCache.fundingIncreaseFactorPerSecond == 0) { - cache.fundingFactor = getFundingFactor(dataStore, market); - uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market)); + cache.fundingFactor = getFundingFactor(dataStore, market.marketToken); + uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market.marketToken)); // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor); @@ -1540,11 +1589,11 @@ library MarketUtils { // if the savedFundingFactorPerSecond is positive then longs pay shorts // if the savedFundingFactorPerSecond is negative then shorts pay longs - cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market); + cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market.marketToken); cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs(); - configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market)); - configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market)); + configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market.marketToken)); + configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market.marketToken)); // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond; @@ -1581,7 +1630,7 @@ library MarketUtils { } if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) { - configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market)); + configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market.marketToken)); uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds; if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) { @@ -1594,8 +1643,8 @@ library MarketUtils { } } - configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market)); - configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market)); + configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market.marketToken)); + configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market.marketToken)); cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude( cache.nextSavedFundingFactorPerSecond, @@ -2030,9 +2079,6 @@ library MarketUtils { return token == market.longToken; } - // @dev get the virtual inventory for positions - // @param dataStore DataStore - // @param token the token to check function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) { bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token)); if (virtualTokenId == bytes32(0)) { @@ -2042,6 +2088,15 @@ library MarketUtils { return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId))); } + function getVirtualInventoryForPositionsInTokens(DataStore dataStore, address token) internal view returns (bool, int256) { + bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token)); + if (virtualTokenId == bytes32(0)) { + return (false, 0); + } + + return (true, dataStore.getInt(Keys.virtualInventoryForPositionsInTokensKey(virtualTokenId))); + } + // @dev update the virtual inventory for swaps // @param dataStore DataStore // @param marketAddress the market to update @@ -2071,11 +2126,6 @@ library MarketUtils { return (true, nextValue); } - // @dev update the virtual inventory for positions - // @param dataStore DataStore - // @param eventEmitter EventEmitter - // @param token the token to update - // @param delta the update amount function applyDeltaToVirtualInventoryForPositions( DataStore dataStore, EventEmitter eventEmitter, @@ -2097,6 +2147,27 @@ library MarketUtils { return (true, nextValue); } + function applyDeltaToVirtualInventoryForPositionsInTokens( + DataStore dataStore, + EventEmitter eventEmitter, + address token, + int256 delta + ) internal returns (bool, int256) { + bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token)); + if (virtualTokenId == bytes32(0)) { + return (false, 0); + } + + int256 nextValue = dataStore.applyDeltaToInt( + Keys.virtualInventoryForPositionsInTokensKey(virtualTokenId), + delta + ); + + MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue); + + return (true, nextValue); + } + // @dev get the open interest of a market // @param dataStore DataStore // @param market the market to check @@ -2112,13 +2183,6 @@ library MarketUtils { return longOpenInterest + shortOpenInterest; } - // @dev get either the long or short open interest for a market - // @param dataStore DataStore - // @param market the market to check - // @param longToken the long token of the market - // @param shortToken the short token of the market - // @param isLong whether to get the long or short open interest - // @return the long or short open interest for a market function getOpenInterest( DataStore dataStore, Market.Props memory market, @@ -2131,11 +2195,6 @@ library MarketUtils { return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral; } - // @dev the long and short open interest for a market based on the collateral token used - // @param dataStore DataStore - // @param market the market to check - // @param collateralToken the collateral token to check - // @param isLong whether to check the long or short side function getOpenInterest( DataStore dataStore, address market, @@ -2146,6 +2205,62 @@ library MarketUtils { return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor; } + function getOpenInterestForBalance( + DataStore dataStore, + Market.Props memory market, + bool useOpenInterestInTokens, + uint256 indexTokenPrice, + bool isLong + ) internal view returns (uint256) { + uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); + + uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestForBalance({ + dataStore: dataStore, + market: market.marketToken, + divisor: divisor, + useOpenInterestInTokens: useOpenInterestInTokens, + indexTokenPrice: indexTokenPrice, + collateralToken: market.longToken, + isLong: isLong + }); + + uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestForBalance({ + dataStore: dataStore, + market: market.marketToken, + divisor: divisor, + useOpenInterestInTokens: useOpenInterestInTokens, + indexTokenPrice: indexTokenPrice, + collateralToken: market.shortToken, + isLong: isLong + }); + + return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral; + } + + function getOpenInterestForBalance( + DataStore dataStore, + address market, + uint256 divisor, + bool useOpenInterestInTokens, + uint256 indexTokenPrice, + address collateralToken, + bool isLong + ) internal view returns (uint256) { + if (useOpenInterestInTokens) { + uint256 openInterestInTokens = getOpenInterestInTokens( + dataStore, + market, + collateralToken, + isLong, + divisor + ); + + return openInterestInTokens * indexTokenPrice; + } + + return getOpenInterest(dataStore, market, collateralToken, isLong, divisor); + } + // this is used to divide the values of getPoolAmount and getOpenInterest // if the longToken and shortToken are the same, then these values have to be divided by two // to avoid double counting @@ -2153,6 +2268,21 @@ library MarketUtils { return longToken == shortToken ? 2 : 1; } + function getOpenInterestInTokensInUsd( + DataStore dataStore, + Market.Props memory market, + bool isLong, + uint256 indexTokenPrice + ) internal view returns (uint256) { + uint256 openInterestInTokens = getOpenInterestInTokens( + dataStore, + market, + isLong + ); + + return openInterestInTokens * indexTokenPrice; + } + // @dev the long and short open interest in tokens for a market // @param dataStore DataStore // @param market the market to check @@ -2635,8 +2765,22 @@ library MarketUtils { // then the borrowing fee would be charged for both sides, this should be very rare bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE); if (skipBorrowingFeeForSmallerSide) { - uint256 longOpenInterest = getOpenInterest(dataStore, market, true); - uint256 shortOpenInterest = getOpenInterest(dataStore, market, false); + bool useOpenInterestInTokens = dataStore.getBool(Keys.USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE); + uint256 longOpenInterest = getOpenInterestForBalance({ + dataStore: dataStore, + market: market, + useOpenInterestInTokens: useOpenInterestInTokens, + indexTokenPrice: prices.indexTokenPrice.midPrice(), + isLong: true + }); + + uint256 shortOpenInterest = getOpenInterestForBalance({ + dataStore: dataStore, + market: market, + useOpenInterestInTokens: useOpenInterestInTokens, + indexTokenPrice: prices.indexTokenPrice.midPrice(), + isLong: false + }); // if getting the borrowing factor for longs and if the longOpenInterest // is smaller than the shortOpenInterest, then return zero diff --git a/contracts/mock/MockStargatePool.sol b/contracts/mock/MockStargatePool.sol index f7e5b0410..a1c7c1add 100644 --- a/contracts/mock/MockStargatePool.sol +++ b/contracts/mock/MockStargatePool.sol @@ -26,6 +26,9 @@ contract MockStargatePool { * @param layerZeroProvider The recipient contract (LayerZeroProvider) * @param _amount The amount of tokens to send * @param _message The encoded message containing account, token, srcChainId + * @dev Simulates real Stargate behavior: + * 1. For ERC20: transfers tokens to LayerZeroProvider, then calls lzCompose with msg.value (top-up) + * 2. For native ETH: transfers bridged ETH to LayerZeroProvider, then calls lzCompose with remaining msg.value (top-up) */ function sendToken(LayerZeroProvider layerZeroProvider, uint256 _amount, bytes calldata _message) external payable { // prepend composeFrom (msg.sender) to the user payload @@ -41,14 +44,25 @@ contract MockStargatePool { encodedMsg ); + uint256 composeValue = msg.value; if (token == address(0)) { - require(msg.value == _amount, "Incorrect ETH amount sent"); + // For native token: msg.value should include both bridged amount + top-up + require(msg.value >= _amount, "Insufficient ETH sent"); + + // Transfer bridged ETH to LayerZeroProvider (simulates Stargate's _outflow) + (bool success, ) = address(layerZeroProvider).call{value: _amount}(""); + require(success, "ETH transfer failed"); + + // Remaining msg.value is the top-up amount for lzCompose + composeValue -= _amount; } else { + // For ERC20: msg.value includes just the top-up IERC20(token).transferFrom(msg.sender, address(layerZeroProvider), _amount); } // Simulate cross-chain message delivery by directly calling lzCompose on the LayerZeroProvider contract - layerZeroProvider.lzCompose{value: msg.value}( + // The composeValue represents ONLY the top-up amount (not the bridged tokens) + layerZeroProvider.lzCompose{value: composeValue}( address(this), bytes32(uint256(1)), // mock guid composedMsg, diff --git a/contracts/multichain/LayerZeroProvider.sol b/contracts/multichain/LayerZeroProvider.sol index 88117b7e8..fb6f7d074 100644 --- a/contracts/multichain/LayerZeroProvider.sol +++ b/contracts/multichain/LayerZeroProvider.sol @@ -105,6 +105,7 @@ contract LayerZeroProvider is IMultichainProvider, ILayerZeroComposer, RoleModul (address account, uint256 srcChainId, uint256 amountLD, bytes memory data) = _decodeLzComposeMsg(message); address token = IStargate(from).token(); + if (token == address(0x0)) { // `from` is StargatePoolNative TokenUtils.depositAndSendWrappedNativeToken(dataStore, address(multichainVault), amountLD); @@ -125,13 +126,25 @@ contract LayerZeroProvider is IMultichainProvider, ILayerZeroComposer, RoleModul srcChainId ); + // Handle native token top-up before other actions to ensure the user has the ability to + // pay relay and execution fees required by subsequent actions (Deposit, Withdrawal, etc.) + uint256 expectedNativeValue = 0; + if (data.length != 0) { + (, uint256 decodedExpectedNativeValue, ) = abi.decode(data, (ActionType, uint256, bytes)); + expectedNativeValue = decodedExpectedNativeValue; + } + if (expectedNativeValue != 0 || msg.value != 0) { + _handleNativeTopUp(account, srcChainId, expectedNativeValue); + } + + // note that for these functions, the remaining gas must be sufficient // otherwise the function will revert // if the action cannot be completed due to gas issues, the user would // need to manually call the function with the right amount of gas // srcChainId could be zero when returned from _decodeLzComposeMsg, skip follow up actions in this case if (srcChainId != 0 && data.length != 0) { - (ActionType actionType, bytes memory actionData) = abi.decode(data, (ActionType, bytes)); + (ActionType actionType, , bytes memory actionData) = abi.decode(data, (ActionType, uint256, bytes)); // this event is emitted even though the actionType may not be valid MultichainEventUtils.emitMultichainBridgeAction(eventEmitter, address(this), account, srcChainId, uint256(actionType)); @@ -338,6 +351,33 @@ contract LayerZeroProvider is IMultichainProvider, ILayerZeroComposer, RoleModul return true; } + function _handleNativeTopUp( + address account, + uint256 srcChainId, + uint256 expectedNativeValue + ) private { + // Enforce msg.value matches expected native top-up amount + // Note: This may cause bridged tokens to be locked if executor underpays, + // but other executors or users can retry lzCompose with correct msg.value + if (msg.value < expectedNativeValue) { + revert Errors.InsufficientNativeTokenAmount(msg.value, expectedNativeValue); + } + + // Allow receiving native tokens alongside bridged tokens to cover execution fees + // msg.value represents ONLY the top-up amount specified in lzComposeOption (not the bridged tokens) + // Bridged tokens are already transferred to this contract separately via Stargate's flow + TokenUtils.depositAndSendWrappedNativeToken(dataStore, address(multichainVault), msg.value); + MultichainUtils.recordBridgeIn( + dataStore, + eventEmitter, + multichainVault, + this, + TokenUtils.wnt(dataStore), + account, + srcChainId + ); + } + /// @dev long/short tokens are deposited from user's multichain balance /// GM tokens are minted and transferred to user's multichain balance function _handleDeposit( diff --git a/contracts/position/DecreasePositionCollateralUtils.sol b/contracts/position/DecreasePositionCollateralUtils.sol index c3b51fc39..fd0a9ae77 100644 --- a/contracts/position/DecreasePositionCollateralUtils.sol +++ b/contracts/position/DecreasePositionCollateralUtils.sol @@ -84,7 +84,6 @@ library DecreasePositionCollateralUtils { params.secondaryOrderType == Order.SecondaryOrderType.Adl ); - (values.priceImpactUsd, values.executionPrice, collateralCache.balanceWasImproved) = PositionUtils.getExecutionPriceForDecrease(params, cache.prices.indexTokenPrice); // the totalPositionPnl is calculated based on the current indexTokenPrice instead of the executionPrice // since the executionPrice factors in price impact which should be accounted for separately @@ -99,6 +98,12 @@ library DecreasePositionCollateralUtils { params.order.sizeDeltaUsd() ); + (values.priceImpactUsd, values.executionPrice, collateralCache.balanceWasImproved) = PositionUtils.getExecutionPriceForDecrease( + params, + cache.prices.indexTokenPrice, + values.sizeDeltaInTokens + ); + PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams( params.contracts.dataStore, // dataStore params.contracts.referralStorage, // referralStorage diff --git a/contracts/position/DecreasePositionUtils.sol b/contracts/position/DecreasePositionUtils.sol index 561e185bc..7068a1a11 100644 --- a/contracts/position/DecreasePositionUtils.sol +++ b/contracts/position/DecreasePositionUtils.sol @@ -323,15 +323,16 @@ library DecreasePositionUtils { // the only difference is that if the position has insufficient / negative // collateral a liquidation transaction should still complete // while a manual close transaction should revert - PositionUtils.validatePosition( - params.contracts.dataStore, - params.contracts.referralStorage, - params.position, - params.market, - cache.prices, - false, // shouldValidateMinPositionSize - false // shouldValidateMinCollateralUsd - ); + PositionUtils.validatePosition({ + dataStore: params.contracts.dataStore, + referralStorage: params.contracts.referralStorage, + position: params.position, + market: params.market, + prices: cache.prices, + shouldValidateMinPositionSize: false, + shouldValidateMinCollateralUsd: false, + forLiquidation: false + }); } PositionEventUtils.emitPositionFeesCollected( diff --git a/contracts/position/IncreasePositionUtils.sol b/contracts/position/IncreasePositionUtils.sol index e7dfe564b..df951508b 100644 --- a/contracts/position/IncreasePositionUtils.sol +++ b/contracts/position/IncreasePositionUtils.sol @@ -210,17 +210,19 @@ library IncreasePositionUtils { PositionUtils.handleReferral(params, fees); - // validatePosition should be called after open interest and all other market variables - // have been updated - PositionUtils.validatePosition( - params.contracts.dataStore, - params.contracts.referralStorage, - params.position, - params.market, - prices, - true, // shouldValidateMinPositionSize - true // shouldValidateMinCollateralUsd - ); + // if order.sizeDeltaUsd == 0, we validate that the position is not liquidatable + // this helps to prevent a deposit from being executed if the position would be + // liquidated shortly after + PositionUtils.validatePosition({ + dataStore: params.contracts.dataStore, + referralStorage: params.contracts.referralStorage, + position: params.position, + market: params.market, + prices: prices, + shouldValidateMinPositionSize: true, + shouldValidateMinCollateralUsd: true, + forLiquidation: params.order.sizeDeltaUsd() == 0 + }); PositionEventUtils.emitPositionFeesCollected( params.contracts.eventEmitter, diff --git a/contracts/position/PositionUtils.sol b/contracts/position/PositionUtils.sol index 9688c1083..53667b527 100644 --- a/contracts/position/PositionUtils.sol +++ b/contracts/position/PositionUtils.sol @@ -244,6 +244,19 @@ library PositionUtils { } } + function validateBasicPositionInfo( + DataStore dataStore, + Position.Props memory position, + Market.Props memory market + ) internal view { + if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) { + revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens()); + } + + MarketUtils.validateEnabledMarket(dataStore, market.marketToken); + MarketUtils.validateMarketCollateralToken(market, position.collateralToken()); + } + // @dev check if a position is valid // @param dataStore DataStore // @param referralStorage IReferralStorage @@ -268,14 +281,10 @@ library PositionUtils { Market.Props memory market, MarketUtils.MarketPrices memory prices, bool shouldValidateMinPositionSize, - bool shouldValidateMinCollateralUsd + bool shouldValidateMinCollateralUsd, + bool forLiquidation ) public view { - if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) { - revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens()); - } - - MarketUtils.validateEnabledMarket(dataStore, market.marketToken); - MarketUtils.validateMarketCollateralToken(market, position.collateralToken()); + validateBasicPositionInfo(dataStore, position, market); if (shouldValidateMinPositionSize) { uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD); @@ -291,7 +300,7 @@ library PositionUtils { market, prices, shouldValidateMinCollateralUsd, - false // forLiquidation + forLiquidation ); if (isLiquidatable) { @@ -339,7 +348,9 @@ library PositionUtils { PositionPricingUtils.GetPriceImpactUsdParams( dataStore, market, + prices.indexTokenPrice, cache.usdDeltaForPriceImpact, + -position.sizeInTokens().toInt256(), position.isLong() ) ); @@ -597,22 +608,27 @@ library PositionUtils { int256 sizeDeltaInTokens ) internal { if (sizeDeltaUsd != 0) { + bool useOpenInterestInTokens = params.contracts.dataStore.getBool(Keys.USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE); + MarketUtils.applyDeltaToOpenInterest( params.contracts.dataStore, params.contracts.eventEmitter, params.market, params.position.collateralToken(), params.position.isLong(), - sizeDeltaUsd + sizeDeltaUsd, + useOpenInterestInTokens ); MarketUtils.applyDeltaToOpenInterestInTokens( params.contracts.dataStore, params.contracts.eventEmitter, params.position.market(), + params.market.indexToken, params.position.collateralToken(), params.position.isLong(), - sizeDeltaInTokens + sizeDeltaInTokens, + useOpenInterestInTokens ); } } @@ -648,11 +664,21 @@ library PositionUtils { GetExecutionPriceForIncreaseCache memory cache; + if (params.position.isLong()) { + // round the number of tokens for long positions down + cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max; + } else { + // round the number of tokens for short positions up + cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min); + } + (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd( PositionPricingUtils.GetPriceImpactUsdParams( params.contracts.dataStore, params.market, + prices.indexTokenPrice, params.order.sizeDeltaUsd().toInt256(), + cache.baseSizeDeltaInTokens.toInt256(), params.order.isLong() ) ); @@ -699,14 +725,6 @@ library PositionUtils { cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min); } - if (params.position.isLong()) { - // round the number of tokens for long positions down - cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max; - } else { - // round the number of tokens for short positions up - cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min); - } - int256 sizeDeltaInTokens; if (params.position.isLong()) { sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount; @@ -737,7 +755,8 @@ library PositionUtils { // returns priceImpactUsd, executionPrice, balanceWasImproved function getExecutionPriceForDecrease( UpdatePositionParams memory params, - Price.Props memory indexTokenPrice + Price.Props memory indexTokenPrice, + uint256 sizeDeltaInTokens ) external view returns (int256, uint256, bool) { uint256 sizeDeltaUsd = params.order.sizeDeltaUsd(); @@ -757,7 +776,9 @@ library PositionUtils { PositionPricingUtils.GetPriceImpactUsdParams( params.contracts.dataStore, params.market, + indexTokenPrice, -sizeDeltaUsd.toInt256(), + -sizeDeltaInTokens.toInt256(), params.order.isLong() ) ); diff --git a/contracts/pricing/PositionPricingUtils.sol b/contracts/pricing/PositionPricingUtils.sol index 39c64e8dc..4d88e07d8 100644 --- a/contracts/pricing/PositionPricingUtils.sol +++ b/contracts/pricing/PositionPricingUtils.sol @@ -53,7 +53,9 @@ library PositionPricingUtils { struct GetPriceImpactUsdParams { DataStore dataStore; Market.Props market; + Price.Props indexTokenPrice; int256 usdDelta; + int256 tokenDelta; bool isLong; } @@ -157,7 +159,8 @@ library PositionPricingUtils { // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) { - OpenInterestParams memory openInterestParams = getNextOpenInterest(params); + bool useOpenInterestInTokens = params.dataStore.getBool(Keys.USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE); + OpenInterestParams memory openInterestParams = getNextOpenInterest(params, useOpenInterestInTokens); (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams); @@ -172,8 +175,18 @@ library PositionPricingUtils { // disincentivise the balancing of pools if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); } - (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken); - if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); } + bool hasVirtualInventory; + int256 virtualInventory; + + if (useOpenInterestInTokens) { + (hasVirtualInventory, virtualInventory) = MarketUtils.getVirtualInventoryForPositionsInTokens(params.dataStore, params.market.indexToken); + virtualInventory = virtualInventory * params.indexTokenPrice.midPrice().toInt256(); + if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); } + } else { + (hasVirtualInventory, virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken); + if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); } + } + OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory); (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory); @@ -229,19 +242,63 @@ library PositionPricingUtils { // @param params GetPriceImpactUsdParams // @return OpenInterestParams function getNextOpenInterest( - GetPriceImpactUsdParams memory params + GetPriceImpactUsdParams memory params, + bool useOpenInterestInTokens ) internal view returns (OpenInterestParams memory) { - uint256 longOpenInterest = MarketUtils.getOpenInterest( - params.dataStore, - params.market, - true - ); + // if useOpenInterestInTokens is true, then the price impact can vary depending on the index token price + // this occurs if a curve is used and the openInterestInTokens is not entirely balanced + // + // balanced case: longOpenInterestInTokens is 1, shortOpenInterestInTokens is 1, price is $5000 + // price impact is 0.01% per $500 + // if sizeDeltaUsd is $1000, then price impact would be 0.02%, this would not change even if the price is different + // + // imbalanced case: longOpenInterestInTokens is 2, shortOpenInterestInTokens is 1, price is $5000 + // if long sizeDeltaUsd is $1000, then the action reduces balance from (2 - 1) * ($5000) = $5000 to $6000 + // if the price is $6000 + // then the action would reduce balance from (2 - 1) * ($6000) = $6000 to $7000 + // + // there is also a case where the sizeDeltaUsd can exceed the openInterestInTokensInUsd value + // e.g. a user opens a 1 index token long and short position at price $5000, so long / short sizeInUsd is 5000, long / short sizeInTokens is 1 + // the index token price decreases to $4500 + // the user decreases the long position + // openInterestInTokensInUsd is $4500 but sizeDeltaUsd is $5000 + // to prevent overflow issues, the tokenDelta is used to calculate the usdDelta if useOpenInterestInTokens is true - uint256 shortOpenInterest = MarketUtils.getOpenInterest( - params.dataStore, - params.market, - false - ); + uint256 longOpenInterest; + uint256 shortOpenInterest; + + if (useOpenInterestInTokens) { + longOpenInterest = MarketUtils.getOpenInterestInTokensInUsd( + params.dataStore, + params.market, + true, + params.indexTokenPrice.midPrice() + ); + + shortOpenInterest = MarketUtils.getOpenInterestInTokensInUsd( + params.dataStore, + params.market, + false, + params.indexTokenPrice.midPrice() + ); + + // note that for decrease position, tokenDelta is based on the + // ratio of position.sizeInUsd and position.sizeInTokens + // so different users would experience different price impacts + // for the same decrease in USD size + params.usdDelta = params.tokenDelta * params.indexTokenPrice.midPrice().toInt256(); + } else { + longOpenInterest = MarketUtils.getOpenInterest( + params.dataStore, + params.market, + true + ); + shortOpenInterest = MarketUtils.getOpenInterest( + params.dataStore, + params.market, + false + ); + } return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest); } @@ -286,18 +343,23 @@ library PositionPricingUtils { uint256 nextLongOpenInterest = longOpenInterest; uint256 nextShortOpenInterest = shortOpenInterest; + // with single token markets, because getOpenInterest is rounded down when divided by two + // it is possible for the usdDelta to exceed the calculated open interest + // to prevent reverts here, nextLongOpenInterest and nextShortOpenInterest is set to 0 for this case + // there is a separate validation in applyDeltaToOpenInterest and applyDeltaToOpenInterestInTokens + // to prevent orders that would result in a negative open interest if (params.isLong) { if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) { - revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest); + nextLongOpenInterest = 0; + } else { + nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta); } - - nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta); } else { if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) { - revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest); + nextShortOpenInterest = 0; + } else { + nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta); } - - nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta); } OpenInterestParams memory openInterestParams = OpenInterestParams( diff --git a/contracts/reader/ReaderPositionUtils.sol b/contracts/reader/ReaderPositionUtils.sol index d0760bc8e..6138ae043 100644 --- a/contracts/reader/ReaderPositionUtils.sol +++ b/contracts/reader/ReaderPositionUtils.sol @@ -32,32 +32,6 @@ library ReaderPositionUtils { uint256 pendingBorrowingFeeUsd; } - function getNextBorrowingFees( - DataStore dataStore, - Position.Props memory position, - Market.Props memory market, - MarketUtils.MarketPrices memory prices - ) internal view returns (uint256) { - return MarketUtils.getNextBorrowingFees( - dataStore, - position, - market, - prices - ); - } - - function getBorrowingFees( - DataStore dataStore, - Price.Props memory collateralTokenPrice, - uint256 borrowingFeeUsd - ) internal view returns (PositionPricingUtils.PositionBorrowingFees memory) { - return PositionPricingUtils.getBorrowingFees( - dataStore, - collateralTokenPrice, - borrowingFeeUsd - ); - } - function getPositionInfoList( DataStore dataStore, IReferralStorage referralStorage, @@ -129,18 +103,6 @@ library ReaderPositionUtils { revert Errors.EmptyMarketPrice(market); } - function getNextFundingAmountPerSize( - DataStore dataStore, - Market.Props memory market, - MarketUtils.MarketPrices memory prices - ) public view returns (MarketUtils.GetNextFundingAmountPerSizeResult memory) { - return MarketUtils.getNextFundingAmountPerSize( - dataStore, - market, - prices - ); - } - function getAccountPositions( DataStore dataStore, address account, @@ -230,15 +192,15 @@ library ReaderPositionUtils { // borrowing and funding fees need to be overwritten with pending values otherwise they // would be using storage values that have not yet been updated - cache.pendingBorrowingFeeUsd = getNextBorrowingFees(dataStore, positionInfo.position, cache.market, prices); + cache.pendingBorrowingFeeUsd = MarketUtils.getNextBorrowingFees(dataStore, positionInfo.position, cache.market, prices); - positionInfo.fees.borrowing = getBorrowingFees( + positionInfo.fees.borrowing = PositionPricingUtils.getBorrowingFees( dataStore, cache.collateralTokenPrice, cache.pendingBorrowingFeeUsd ); - MarketUtils.GetNextFundingAmountPerSizeResult memory nextFundingAmountResult = getNextFundingAmountPerSize(dataStore, cache.market, prices); + MarketUtils.GetNextFundingAmountPerSizeResult memory nextFundingAmountResult = MarketUtils.getNextFundingAmountPerSize(dataStore, cache.market, prices); positionInfo.fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize( dataStore, diff --git a/contracts/reader/ReaderPricingUtils.sol b/contracts/reader/ReaderPricingUtils.sol index 6921d1934..51e861264 100644 --- a/contracts/reader/ReaderPricingUtils.sol +++ b/contracts/reader/ReaderPricingUtils.sol @@ -171,9 +171,18 @@ library ReaderPricingUtils { prices ); } else { - (result.priceImpactUsd, result.executionPrice, result.balanceWasImproved) = PositionUtils.getExecutionPriceForDecrease( + (/* basePnlUsd */, /* uncappedBasePnlUsd */, uint256 sizeDeltaInTokens) = PositionUtils.getPositionPnlUsd( + dataStore, + market, + prices, + params.position, + params.order.sizeDeltaUsd() + ); + + (result.priceImpactUsd, result.executionPrice, result.balanceWasImproved) = PositionUtils.getExecutionPriceForDecrease( params, - prices.indexTokenPrice + prices.indexTokenPrice, + sizeDeltaInTokens ); result.proportionalPendingImpactUsd = _getProportionalPendingImpactValues( diff --git a/contracts/reader/ReaderUtils.sol b/contracts/reader/ReaderUtils.sol index 8a9d62557..eba595c1f 100644 --- a/contracts/reader/ReaderUtils.sol +++ b/contracts/reader/ReaderUtils.sol @@ -174,7 +174,7 @@ library ReaderUtils { BaseFundingValues memory baseFunding = getBaseFundingValues(dataStore, market); - MarketUtils.GetNextFundingAmountPerSizeResult memory nextFunding = ReaderPositionUtils.getNextFundingAmountPerSize( + MarketUtils.GetNextFundingAmountPerSizeResult memory nextFunding = MarketUtils.getNextFundingAmountPerSize( dataStore, market, prices diff --git a/deploy/deployContributorHandler.ts b/deploy/deployContributorHandler.ts index 8f1b23424..478bd3488 100644 --- a/deploy/deployContributorHandler.ts +++ b/deploy/deployContributorHandler.ts @@ -13,6 +13,10 @@ const func = createDeployFunction({ afterDeploy: async ({ deployedContract }) => { await grantRoleIfNotGranted(deployedContract, "CONTROLLER"); }, + // NOTE: this id should not be changed unless absolutely necessary + // if a new ContributorHandler is deployed, the funding accounts / treasuries + // would need to re-approve spending of tokens for the new ContributorHandler + id: "ContributorHandler_1", }); func.skip = async (hre: HardhatRuntimeEnvironment) => { diff --git a/deployments/arbitrum/.migrations.json b/deployments/arbitrum/.migrations.json index 38f163803..be266b281 100644 --- a/deployments/arbitrum/.migrations.json +++ b/deployments/arbitrum/.migrations.json @@ -22,5 +22,6 @@ "ClaimVault_1": 1753240024, "ChainlinkPriceFeedProvider_6": 1755053077, "Oracle_6": 1755053081, - "ChainlinkDataStreamProvider_6": 1755053143 + "ChainlinkDataStreamProvider_6": 1755053143, + "ContributorHandler_1": 1760597761 } \ No newline at end of file diff --git a/deployments/arbitrum/ConfigTimelockController.json b/deployments/arbitrum/ConfigTimelockController.json index 5984cedad..2741f72cb 100644 --- a/deployments/arbitrum/ConfigTimelockController.json +++ b/deployments/arbitrum/ConfigTimelockController.json @@ -1,5 +1,5 @@ { - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "abi": [ { "inputs": [ @@ -1057,22 +1057,22 @@ "type": "receive" } ], - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", - "transactionIndex": 4, - "gasUsed": "2740391", - "logsBloom": "0x000008040000000008000000040000010a0020000000000000800020000002000000000000000000000000000001000000000000000000000200000010200000000000000000000000000010000000000008000000000000000000000001000000000000020010400000000480000800000008000000000000020000000002000000000000000000000000000000000000000000000000080000000000000000000000800020000000000000000000004000000000000000001100000000000000000000200000004000000000000000000200000000000100000100a00020000000000040001000008000000000000000000000000000000000000000010000", - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e", - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", + "contractAddress": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", + "transactionIndex": 6, + "gasUsed": "2656728", + "logsBloom": "0x000008040000000008000000040000010a0020000000000000000000000000000000000000000000000000000001000000000000000000000200000010200000020000000000000000000010000000000008000000000000000002020001000000000000020000400000000480000800000000000000200000020000000002000000000000000000000000040000000000000000000000080000000000000000000000000020000000000000000000004000000000000000001100000000000000000000200000004000000000000000000200000000000100000100a00020000000100040001000008000000000000000000000000000000000000000010000", + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e", + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", "logs": [ { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", @@ -1080,14 +1080,14 @@ "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" ], "data": "0x", - "logIndex": 10, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 15, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", @@ -1095,14 +1095,14 @@ "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" ], "data": "0x", - "logIndex": 11, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 16, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", @@ -1110,14 +1110,14 @@ "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" ], "data": "0x", - "logIndex": 12, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 17, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", "0xfd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", @@ -1125,29 +1125,29 @@ "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" ], "data": "0x", - "logIndex": 13, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 18, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", - "0x0000000000000000000000008c6e20a2211d1b70cd7c0789ece44fdb19567621", + "0x000000000000000000000000dd67459d3e98eddaa9770ebb7c38ff8f643f229f", "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 14, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 19, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", @@ -1155,14 +1155,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 15, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 20, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", @@ -1170,14 +1170,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 16, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 21, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xfd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", @@ -1185,14 +1185,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 17, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 22, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", @@ -1200,14 +1200,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 18, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 23, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xfd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", @@ -1215,14 +1215,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 19, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 24, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", @@ -1230,14 +1230,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 20, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 25, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xfd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", @@ -1245,14 +1245,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 21, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 26, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", @@ -1260,14 +1260,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 22, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 27, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xfd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", @@ -1275,14 +1275,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 23, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 28, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", @@ -1290,14 +1290,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 24, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 29, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", @@ -1305,14 +1305,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 25, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 30, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", @@ -1320,14 +1320,14 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 26, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 31, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", @@ -1335,24 +1335,24 @@ "0x000000000000000000000000e7bfff2ab721264887230037940490351700a068" ], "data": "0x", - "logIndex": 27, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 32, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" }, { - "transactionIndex": 4, - "blockNumber": 367848285, - "transactionHash": "0xd70ab3b75dc6a28369e03802ff242eeab19805bb5a30309f54d3fe35d7635c0f", - "address": "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621", + "transactionIndex": 6, + "blockNumber": 390053958, + "transactionHash": "0xc7123eb119ff8f555007c4511b11bd193c21f54015e35b2c1d3046d9782bcee1", + "address": "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f", "topics": [ "0x11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015180", - "logIndex": 28, - "blockHash": "0x847fab03de95b49e9baf6a1f163af941d77c1f6ab1993ee36daf2bf54571ce0e" + "logIndex": 33, + "blockHash": "0x7f48e0447e6ce5fe17c047b7d371c8f84ea93ab45cd73aa49cd8d3285d06626e" } ], - "blockNumber": 367848285, - "cumulativeGasUsed": "3165483", + "blockNumber": 390053958, + "cumulativeGasUsed": "3311804", "status": 1, "byzantium": true }, @@ -1374,13 +1374,13 @@ "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", "0xC8ee91A54287DB53897056e12D9819156D3822Fb" ], - "numDeployments": 4, - "solcInputHash": "1085fa0bbd9d8812a88d39eedbba618e", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minDelay\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"proposers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"executors\",\"type\":\"address[]\"},{\"internalType\":\"contract Oracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"contract DataStore\",\"name\":\"_dataStore\",\"type\":\"address\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"_eventEmitter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"role\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"CallExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"CallSalt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"CallScheduled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"Cancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldDuration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newDuration\",\"type\":\"uint256\"}],\"name\":\"MinDelayChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CANCELLER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXECUTOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TIMELOCK_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dataStore\",\"outputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventEmitter\",\"outputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"providers\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct OracleUtils.SetPricesParams\",\"name\":\"oracleParams\",\"type\":\"tuple\"}],\"name\":\"executeWithOraclePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMinDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"hashOperation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"hashOperationBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationDone\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationReady\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract IOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fundingAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"reductionAmount\",\"type\":\"uint256\"}],\"name\":\"reduceLentImpactAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"schedule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"scheduleBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newDelay\",\"type\":\"uint256\"}],\"name\":\"updateDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFromPositionImpactPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"CallExecuted(bytes32,uint256,address,uint256,bytes)\":{\"details\":\"Emitted when a call is performed as part of operation `id`.\"},\"CallSalt(bytes32,bytes32)\":{\"details\":\"Emitted when new proposal is scheduled with non-zero salt.\"},\"CallScheduled(bytes32,uint256,address,uint256,bytes,bytes32,uint256)\":{\"details\":\"Emitted when a call is scheduled as part of operation `id`.\"},\"Cancelled(bytes32)\":{\"details\":\"Emitted when operation `id` is cancelled.\"},\"MinDelayChange(uint256,uint256)\":{\"details\":\"Emitted when the minimum delay for future operations is modified.\"},\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"cancel(bytes32)\":{\"details\":\"Cancel an operation. Requirements: - the caller must have the 'canceller' role.\"},\"execute(address,uint256,bytes,bytes32,bytes32)\":{\"details\":\"Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements: - the caller must have the 'executor' role.\"},\"executeBatch(address[],uint256[],bytes[],bytes32,bytes32)\":{\"details\":\"Execute an (ready) operation containing a batch of transactions. Emits one {CallExecuted} event per transaction in the batch. Requirements: - the caller must have the 'executor' role.\"},\"getMinDelay()\":{\"details\":\"Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls `updateDelay`.\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getTimestamp(bytes32)\":{\"details\":\"Returns the timestamp at which an operation becomes ready (0 for unset operations, 1 for done operations).\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"hashOperation(address,uint256,bytes,bytes32,bytes32)\":{\"details\":\"Returns the identifier of an operation containing a single transaction.\"},\"hashOperationBatch(address[],uint256[],bytes[],bytes32,bytes32)\":{\"details\":\"Returns the identifier of an operation containing a batch of transactions.\"},\"isOperation(bytes32)\":{\"details\":\"Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.\"},\"isOperationDone(bytes32)\":{\"details\":\"Returns whether an operation is done or not.\"},\"isOperationPending(bytes32)\":{\"details\":\"Returns whether an operation is pending or not. Note that a \\\"pending\\\" operation may also be \\\"ready\\\".\"},\"isOperationReady(bytes32)\":{\"details\":\"Returns whether an operation is ready for execution. Note that a \\\"ready\\\" operation is also \\\"pending\\\".\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"schedule(address,uint256,bytes,bytes32,bytes32,uint256)\":{\"details\":\"Schedule an operation containing a single transaction. Emits {CallSalt} if salt is nonzero, and {CallScheduled}. Requirements: - the caller must have the 'proposer' role.\"},\"scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)\":{\"details\":\"Schedule an operation containing a batch of transactions. Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch. Requirements: - the caller must have the 'proposer' role.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateDelay(uint256)\":{\"details\":\"Changes the minimum timelock duration for future operations. Emits a {MinDelayChange} event. Requirements: - the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/config/ConfigTimelockController.sol\":\"ConfigTimelockController\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorInterface {\\n function latestAnswer() external view returns (int256);\\n\\n function latestTimestamp() external view returns (uint256);\\n\\n function latestRound() external view returns (uint256);\\n\\n function getAnswer(uint256 roundId) external view returns (int256);\\n\\n function getTimestamp(uint256 roundId) external view returns (uint256);\\n\\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\\n\\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\\n}\\n\",\"keccak256\":\"0xb496651006b9a2a07920ffe116928b11e2a6458e21361cecca51409522488ca7\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {AggregatorInterface} from \\\"./AggregatorInterface.sol\\\";\\nimport {AggregatorV3Interface} from \\\"./AggregatorV3Interface.sol\\\";\\n\\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\\n\",\"keccak256\":\"0xee12d80dbdbb3cc0ec10372b9323e42fae9a6de45da5a4e9f7a75223a0b5268b\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n function getRoundData(\\n uint80 _roundId\\n ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n\\n function latestRoundData()\\n external\\n view\\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n}\\n\",\"keccak256\":\"0xfe4e8bb4861bb3860ba890ab91a3b818ec66e5a8f544fb608cfcb73f433472cd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```solidity\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```solidity\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\\n * to enforce additional security measures for this role.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role);\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\\n * Overriding this function changes the behavior of the {onlyRole} modifier.\\n *\\n * Format of the revert message is described in {_checkRole}.\\n *\\n * _Available since v4.6._\\n */\\n function _checkRole(bytes32 role) internal view virtual {\\n _checkRole(role, _msgSender());\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view virtual {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(account),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * May emit a {RoleGranted} event.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n *\\n * NOTE: This function is deprecated in favor of {_grantRole}.\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n bytes32 previousAdminRole = getRoleAdmin(role);\\n _roles[role].adminRole = adminRole;\\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function _grantRole(bytes32 role, address account) internal virtual {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function _revokeRole(bytes32 role, address account) internal virtual {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0dd6e52cb394d7f5abe5dca2d4908a6be40417914720932de757de34a99ab87f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/governance/TimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../access/AccessControl.sol\\\";\\nimport \\\"../token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"../token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Contract module which acts as a timelocked controller. When set as the\\n * owner of an `Ownable` smart contract, it enforces a timelock on all\\n * `onlyOwner` maintenance operations. This gives time for users of the\\n * controlled contract to exit before a potentially dangerous maintenance\\n * operation is applied.\\n *\\n * By default, this contract is self administered, meaning administration tasks\\n * have to go through the timelock process. The proposer (resp executor) role\\n * is in charge of proposing (resp executing) operations. A common use case is\\n * to position this {TimelockController} as the owner of a smart contract, with\\n * a multisig or a DAO as the sole proposer.\\n *\\n * _Available since v3.3._\\n */\\ncontract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {\\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\\\"TIMELOCK_ADMIN_ROLE\\\");\\n bytes32 public constant PROPOSER_ROLE = keccak256(\\\"PROPOSER_ROLE\\\");\\n bytes32 public constant EXECUTOR_ROLE = keccak256(\\\"EXECUTOR_ROLE\\\");\\n bytes32 public constant CANCELLER_ROLE = keccak256(\\\"CANCELLER_ROLE\\\");\\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\\n\\n mapping(bytes32 => uint256) private _timestamps;\\n uint256 private _minDelay;\\n\\n /**\\n * @dev Emitted when a call is scheduled as part of operation `id`.\\n */\\n event CallScheduled(\\n bytes32 indexed id,\\n uint256 indexed index,\\n address target,\\n uint256 value,\\n bytes data,\\n bytes32 predecessor,\\n uint256 delay\\n );\\n\\n /**\\n * @dev Emitted when a call is performed as part of operation `id`.\\n */\\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\\n\\n /**\\n * @dev Emitted when new proposal is scheduled with non-zero salt.\\n */\\n event CallSalt(bytes32 indexed id, bytes32 salt);\\n\\n /**\\n * @dev Emitted when operation `id` is cancelled.\\n */\\n event Cancelled(bytes32 indexed id);\\n\\n /**\\n * @dev Emitted when the minimum delay for future operations is modified.\\n */\\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\\n\\n /**\\n * @dev Initializes the contract with the following parameters:\\n *\\n * - `minDelay`: initial minimum delay for operations\\n * - `proposers`: accounts to be granted proposer and canceller roles\\n * - `executors`: accounts to be granted executor role\\n * - `admin`: optional account to be granted admin role; disable with zero address\\n *\\n * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment\\n * without being subject to delay, but this role should be subsequently renounced in favor of\\n * administration through timelocked proposals. Previous versions of this contract would assign\\n * this admin to the deployer automatically and should be renounced as well.\\n */\\n constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {\\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);\\n\\n // self administration\\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\\n\\n // optional admin\\n if (admin != address(0)) {\\n _setupRole(TIMELOCK_ADMIN_ROLE, admin);\\n }\\n\\n // register proposers and cancellers\\n for (uint256 i = 0; i < proposers.length; ++i) {\\n _setupRole(PROPOSER_ROLE, proposers[i]);\\n _setupRole(CANCELLER_ROLE, proposers[i]);\\n }\\n\\n // register executors\\n for (uint256 i = 0; i < executors.length; ++i) {\\n _setupRole(EXECUTOR_ROLE, executors[i]);\\n }\\n\\n _minDelay = minDelay;\\n emit MinDelayChange(0, minDelay);\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only by a certain role. In\\n * addition to checking the sender's role, `address(0)` 's role is also\\n * considered. Granting a role to `address(0)` is equivalent to enabling\\n * this role for everyone.\\n */\\n modifier onlyRoleOrOpenRole(bytes32 role) {\\n if (!hasRole(role, address(0))) {\\n _checkRole(role, _msgSender());\\n }\\n _;\\n }\\n\\n /**\\n * @dev Contract might receive/hold ETH as part of the maintenance process.\\n */\\n receive() external payable {}\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns whether an id correspond to a registered operation. This\\n * includes both Pending, Ready and Done operations.\\n */\\n function isOperation(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > 0;\\n }\\n\\n /**\\n * @dev Returns whether an operation is pending or not. Note that a \\\"pending\\\" operation may also be \\\"ready\\\".\\n */\\n function isOperationPending(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns whether an operation is ready for execution. Note that a \\\"ready\\\" operation is also \\\"pending\\\".\\n */\\n function isOperationReady(bytes32 id) public view virtual returns (bool) {\\n uint256 timestamp = getTimestamp(id);\\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\\n }\\n\\n /**\\n * @dev Returns whether an operation is done or not.\\n */\\n function isOperationDone(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) == _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns the timestamp at which an operation becomes ready (0 for\\n * unset operations, 1 for done operations).\\n */\\n function getTimestamp(bytes32 id) public view virtual returns (uint256) {\\n return _timestamps[id];\\n }\\n\\n /**\\n * @dev Returns the minimum delay for an operation to become valid.\\n *\\n * This value can be changed by executing an operation that calls `updateDelay`.\\n */\\n function getMinDelay() public view virtual returns (uint256) {\\n return _minDelay;\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a single\\n * transaction.\\n */\\n function hashOperation(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(target, value, data, predecessor, salt));\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a batch of\\n * transactions.\\n */\\n function hashOperationBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(targets, values, payloads, predecessor, salt));\\n }\\n\\n /**\\n * @dev Schedule an operation containing a single transaction.\\n *\\n * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function schedule(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\\n _schedule(id, delay);\\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation containing a batch of transactions.\\n *\\n * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function scheduleBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n _schedule(id, delay);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);\\n }\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation that is to become valid after a given delay.\\n */\\n function _schedule(bytes32 id, uint256 delay) private {\\n require(!isOperation(id), \\\"TimelockController: operation already scheduled\\\");\\n require(delay >= getMinDelay(), \\\"TimelockController: insufficient delay\\\");\\n _timestamps[id] = block.timestamp + delay;\\n }\\n\\n /**\\n * @dev Cancel an operation.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'canceller' role.\\n */\\n function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {\\n require(isOperationPending(id), \\\"TimelockController: operation cannot be cancelled\\\");\\n delete _timestamps[id];\\n\\n emit Cancelled(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a single transaction.\\n *\\n * Emits a {CallExecuted} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function execute(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n bytes32 id = hashOperation(target, value, payload, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n _execute(target, value, payload);\\n emit CallExecuted(id, 0, target, value, payload);\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a batch of transactions.\\n *\\n * Emits one {CallExecuted} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n address target = targets[i];\\n uint256 value = values[i];\\n bytes calldata payload = payloads[i];\\n _execute(target, value, payload);\\n emit CallExecuted(id, i, target, value, payload);\\n }\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an operation's call.\\n */\\n function _execute(address target, uint256 value, bytes calldata data) internal virtual {\\n (bool success, ) = target.call{value: value}(data);\\n require(success, \\\"TimelockController: underlying transaction reverted\\\");\\n }\\n\\n /**\\n * @dev Checks before execution of an operation's calls.\\n */\\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \\\"TimelockController: missing dependency\\\");\\n }\\n\\n /**\\n * @dev Checks after execution of an operation's calls.\\n */\\n function _afterCall(bytes32 id) private {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n _timestamps[id] = _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Changes the minimum timelock duration for future operations.\\n *\\n * Emits a {MinDelayChange} event.\\n *\\n * Requirements:\\n *\\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\\n */\\n function updateDelay(uint256 newDelay) external virtual {\\n require(msg.sender == address(this), \\\"TimelockController: caller must be timelock\\\");\\n emit MinDelayChange(_minDelay, newDelay);\\n _minDelay = newDelay;\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xda2a70247fda81633d9392f567a401c4772837de6b0543c1c561ca632a2fe7f4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/config/ConfigTimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {EventUtils} from \\\"../event/EventUtils.sol\\\";\\nimport {Multicall3} from \\\"../mock/Multicall3.sol\\\";\\nimport {OracleStore} from \\\"../oracle/OracleStore.sol\\\";\\nimport {RoleStore} from \\\"../role/RoleStore.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {TimelockController} from \\\"@openzeppelin/contracts/governance/TimelockController.sol\\\";\\nimport {OracleModule} from \\\"../oracle/OracleModule.sol\\\";\\nimport {OracleUtils} from \\\"../oracle/OracleUtils.sol\\\";\\nimport {Oracle} from \\\"../oracle/Oracle.sol\\\";\\nimport {PositionImpactPoolUtils} from \\\"../market/PositionImpactPoolUtils.sol\\\";\\nimport {Chain} from \\\"../chain/Chain.sol\\\";\\nimport {AccountUtils} from \\\"../utils/AccountUtils.sol\\\";\\n\\ncontract ConfigTimelockController is TimelockController, OracleModule {\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n\\n constructor(\\n uint256 minDelay,\\n address[] memory proposers,\\n address[] memory executors,\\n Oracle oracle,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter\\n ) TimelockController(minDelay, proposers, executors, msg.sender) OracleModule(oracle) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n }\\n\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n // note that if on-chain prices are used for market operations, there may\\n // be some difference in pricing between the on-chain price and e.g.\\n // an off-chain data stream price\\n // it should be ensured that the changes to the market token price that\\n // result from this execution are not too large that it would lead to\\n // significant arbitrage opportunities\\n function executeWithOraclePrices(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt,\\n OracleUtils.SetPricesParams calldata oracleParams\\n ) external onlyRoleOrOpenRole(EXECUTOR_ROLE) withOraclePricesForAtomicAction(oracleParams) {\\n execute(target, value, payload, predecessor, salt);\\n }\\n\\n function withdrawFromPositionImpactPool(\\n address market,\\n address receiver,\\n uint256 amount\\n ) external onlySelf {\\n PositionImpactPoolUtils.withdrawFromPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentImpactAmount(\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external onlySelf {\\n PositionImpactPoolUtils.reduceLentAmount(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n fundingAccount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xfd4e8cf25c70dc3e8b14f59067edbacd134a7e3a1294250f7b0392049b51ddbf\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/market/PositionImpactPoolUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {Market} from \\\"./Market.sol\\\";\\nimport {MarketEventUtils} from \\\"./MarketEventUtils.sol\\\";\\nimport {MarketPoolValueInfo} from \\\"./MarketPoolValueInfo.sol\\\";\\nimport {MarketStoreUtils} from \\\"./MarketStoreUtils.sol\\\";\\nimport {MarketToken} from \\\"./MarketToken.sol\\\";\\nimport {MarketUtils} from \\\"./MarketUtils.sol\\\";\\nimport {SafeCast} from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IOracle } from \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../position/PositionUtils.sol\\\";\\n\\nlibrary PositionImpactPoolUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n using SafeERC20 for IERC20;\\n\\n using Market for Market.Props;\\n\\n // @dev withdraw funds from the position impact pool while maintaining GM token price\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param receiver the address to receive the withdrawn funds\\n // @param amount the amount to withdraw\\n // @param oracle - oracle to fetch the market prices\\n function withdrawFromPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n require(amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n MarketUtils.distributePositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market\\n );\\n\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\\n dataStore,\\n marketProps,\\n prices.indexTokenPrice,\\n prices.longTokenPrice,\\n prices.shortTokenPrice,\\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\\n false\\n );\\n\\n if (poolValueInfo.poolValue <= 0) {\\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\\n }\\n\\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\\n\\n // if there is a positive totalPendingImpactAmount, that means that the\\n // excess should be covered by the position impact pool, so subtract this\\n // from the impactPoolAmount that can be withdrawn\\n // lent amount is not considered here, because if there is a lent amount\\n // we assume that the position impact would be zero\\n if (totalPendingImpactAmount > 0) {\\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\\n }\\n\\n if (adjustedImpactPoolAmount < amount) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n MarketUtils.applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n - amount.toInt256()\\n );\\n\\n // Calculate amount of tokens to withdraw:\\n // We want to withdraw long and short tokens from the pool\\n // at the current pool token ratio\\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\\n dataStore,\\n marketProps,\\n prices,\\n amount * prices.indexTokenPrice.min\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n - longTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n - shortTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.longToken,\\n receiver,\\n longTokenWithdrawalAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.shortToken,\\n receiver,\\n shortTokenWithdrawalAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\\n eventEmitter,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external {\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\\n\\n if (reductionAmount > lentAmount) {\\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\\n }\\n\\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\\n\\n if (longTokenAmount > 0) {\\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\\n }\\n\\n if (shortTokenAmount > 0) {\\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\\n }\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n longTokenAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n shortTokenAmount.toInt256()\\n );\\n\\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitLentImpactAmountReduction(\\n eventEmitter,\\n market,\\n fundingAccount,\\n longTokenAmount,\\n shortTokenAmount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe74b2dfdd27d92eb33535d5c5fe4af456d05c180d17d8252f5728c62dd1293b0\",\"license\":\"BUSL-1.1\"},\"contracts/mock/Multicall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title Multicall3\\n/// @notice Aggregate results from multiple function calls\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract Multicall3 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked { valAccumulator += val; }\\n (result.success, result.returnData) = calli.target.call{value: val}(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked { ++i; }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x403295008f09f7f5911396b6243d95bd4084e8f6e085af2b958a4af64c29e07c\",\"license\":\"MIT\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/ChainlinkPriceFeedUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./IPriceFeed.sol\\\";\\n\\n// @title ChainlinkPriceFeedProviderUtils\\n// @dev Library for Chainlink price feed\\nlibrary ChainlinkPriceFeedUtils {\\n // there is a small risk of stale pricing due to latency in price updates or if the chain is down\\n // this is meant to be for temporary use until low latency price feeds are supported for all tokens\\n function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {\\n address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));\\n if (priceFeedAddress == address(0)) {\\n return (false, 0);\\n }\\n\\n IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);\\n\\n (\\n /* uint80 roundID */,\\n int256 _price,\\n /* uint256 startedAt */,\\n uint256 timestamp,\\n /* uint80 answeredInRound */\\n ) = priceFeed.latestRoundData();\\n\\n if (_price <= 0) {\\n revert Errors.InvalidFeedPrice(token, _price);\\n }\\n\\n uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));\\n if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {\\n revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);\\n }\\n\\n uint256 price = SafeCast.toUint256(_price);\\n uint256 precision = getPriceFeedMultiplier(dataStore, token);\\n\\n uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);\\n\\n return (true, adjustedPrice);\\n }\\n\\n // @dev get the multiplier value to convert the external price feed price to the price of 1 unit of the token\\n // represented with 30 decimals\\n // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of\\n // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)\\n // if the external price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8)\\n // in this case the priceFeedMultiplier should be 10 ^ 46\\n // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24)\\n // formula for decimals for price feed multiplier: 60 - (external price feed decimals) - (token decimals)\\n //\\n // @param dataStore DataStore\\n // @param token the token to get the price feed multiplier for\\n // @return the price feed multipler\\n function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {\\n uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));\\n\\n if (multiplier == 0) {\\n revert Errors.EmptyChainlinkPriceFeedMultiplier(token);\\n }\\n\\n return multiplier;\\n }\\n}\\n\",\"keccak256\":\"0xf2abeec57d21410a8306356562077b0aedb77f15be6a5d1451c915c0c20b2fe6\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OracleUtils.sol\\\";\\n\\n// @title IOracleProvider\\n// @dev Interface for an oracle provider\\ninterface IOracleProvider {\\n function getOraclePrice(\\n address token,\\n bytes memory data\\n ) external returns (OracleUtils.ValidatedPrice memory);\\n\\n /// @dev for all oracle providers besides ChainlinkPriceFeedProvider\\n function shouldAdjustTimestamp() external pure returns (bool);\\n\\n /// @dev for ChainlinkPriceFeedProvider\\n function isChainlinkOnChainProvider() external pure returns (bool);\\n}\\n\",\"keccak256\":\"0x8d58f6373f8894c71e559e845db06043047c4ccdf9fac827f8cdf41044b3b1f6\",\"license\":\"MIT\"},\"contracts/oracle/IPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n// @title IPriceFeed\\n// @dev Interface for a price feed\\ninterface IPriceFeed {\\n function latestRoundData() external view returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function description() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x5474d86a80fde875ffd0b52d2806554b32bf10c33553ecae7de1f82400bcf5b6\",\"license\":\"MIT\"},\"contracts/oracle/Oracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport { AggregatorV2V3Interface } from \\\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\\\";\\n\\nimport \\\"../role/RoleModule.sol\\\";\\n\\nimport \\\"./OracleUtils.sol\\\";\\nimport \\\"./IOracle.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\nimport \\\"./ChainlinkPriceFeedUtils.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\nimport \\\"../utils/Uint256Mask.sol\\\";\\n\\n// @title Oracle\\n// @dev Contract to validate and store signed values\\n// Some calculations e.g. calculating the size in tokens for a position\\n// may not work with zero / negative prices\\n// as a result, zero / negative prices are considered empty / invalid\\n// A market may need to be manually settled in this case\\ncontract Oracle is IOracle, RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using Price for Price.Props;\\n using Uint256Mask for Uint256Mask.Mask;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n AggregatorV2V3Interface public immutable sequencerUptimeFeed;\\n\\n // tokensWithPrices stores the tokens with prices that have been set\\n // this is used in clearAllPrices to help ensure that all token prices\\n // set in setPrices are cleared after use\\n EnumerableSet.AddressSet internal tokensWithPrices;\\n mapping(address => Price.Props) public primaryPrices;\\n\\n uint256 public minTimestamp;\\n uint256 public maxTimestamp;\\n\\n constructor(\\n RoleStore _roleStore,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter,\\n AggregatorV2V3Interface _sequencerUptimeFeed\\n ) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n sequencerUptimeFeed = _sequencerUptimeFeed;\\n }\\n\\n // this can be used to help ensure that on-chain prices are updated\\n // before actions dependent on those on-chain prices are allowed\\n // additionally, this can also be used to provide a grace period for\\n // users to top up collateral before liquidations occur\\n function validateSequencerUp() public view {\\n if (address(sequencerUptimeFeed) == address(0)) {\\n return;\\n }\\n\\n (\\n /*uint80 roundID*/,\\n int256 answer,\\n uint256 startedAt,\\n /*uint256 updatedAt*/,\\n /*uint80 answeredInRound*/\\n ) = sequencerUptimeFeed.latestRoundData();\\n\\n // answer == 0: sequencer is up\\n // answer == 1: sequencer is down\\n bool isSequencerUp = answer == 0;\\n if (!isSequencerUp) {\\n revert Errors.SequencerDown();\\n }\\n\\n uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);\\n\\n // ensure the grace duration has passed after the\\n // sequencer is back up.\\n uint256 timeSinceUp = block.timestamp - startedAt;\\n if (timeSinceUp <= sequencerGraceDuration) {\\n revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);\\n }\\n }\\n\\n function setPrices(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);\\n\\n _setPrices(prices);\\n }\\n\\n function setPricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n validateSequencerUp();\\n\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);\\n\\n _setPrices(prices);\\n }\\n\\n // @dev set the primary price\\n // @param token the token to set the price for\\n // @param price the price value to set to\\n function setPrimaryPrice(address token, Price.Props memory price) external onlyController {\\n _setPrimaryPrice(token, price);\\n }\\n\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n // @dev clear all prices\\n function clearAllPrices() external onlyController {\\n uint256 length = tokensWithPrices.length();\\n for (uint256 i; i < length; i++) {\\n address token = tokensWithPrices.at(0);\\n _removePrimaryPrice(token);\\n }\\n\\n minTimestamp = 0;\\n maxTimestamp = 0;\\n }\\n\\n // @dev get the length of tokensWithPrices\\n // @return the length of tokensWithPrices\\n function getTokensWithPricesCount() external view returns (uint256) {\\n return tokensWithPrices.length();\\n }\\n\\n // @dev get the tokens of tokensWithPrices for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the tokens of tokensWithPrices for the specified indexes\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {\\n return tokensWithPrices.valuesAt(start, end);\\n }\\n\\n // @dev get the primary price of a token\\n // @param token the token to get the price for\\n // @return the primary price of a token\\n function getPrimaryPrice(address token) external view returns (Price.Props memory) {\\n if (token == address(0)) { return Price.Props(0, 0); }\\n\\n Price.Props memory price = primaryPrices[token];\\n if (price.isEmpty()) {\\n revert Errors.EmptyPrimaryPrice(token);\\n }\\n\\n return price;\\n }\\n\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {\\n return _validatePrices(params, forAtomicAction);\\n }\\n\\n // @dev validate and set prices\\n // @param params OracleUtils.SetPricesParams\\n function _setPrices(\\n OracleUtils.ValidatedPrice[] memory prices\\n ) internal {\\n // in case of gasless relay the prices are not required if there is no need to swap fee tokens\\n if (prices.length == 0) {\\n return;\\n }\\n\\n if (tokensWithPrices.length() != 0) {\\n revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());\\n }\\n\\n uint256 _minTimestamp = prices[0].timestamp;\\n uint256 _maxTimestamp = prices[0].timestamp;\\n\\n for (uint256 i; i < prices.length; i++) {\\n OracleUtils.ValidatedPrice memory validatedPrice = prices[i];\\n\\n _setPrimaryPrice(validatedPrice.token, Price.Props(\\n validatedPrice.min,\\n validatedPrice.max\\n ));\\n\\n if (validatedPrice.timestamp < _minTimestamp) {\\n _minTimestamp = validatedPrice.timestamp;\\n }\\n\\n if (validatedPrice.timestamp > _maxTimestamp) {\\n _maxTimestamp = validatedPrice.timestamp;\\n }\\n\\n _emitOraclePriceUpdated(\\n validatedPrice.token,\\n validatedPrice.min,\\n validatedPrice.max,\\n validatedPrice.timestamp,\\n validatedPrice.provider\\n );\\n }\\n\\n uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);\\n if (_maxTimestamp - _minTimestamp > maxRange) {\\n revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);\\n }\\n\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n function _validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) internal returns (OracleUtils.ValidatedPrice[] memory) {\\n if (params.tokens.length != params.providers.length) {\\n revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);\\n }\\n\\n if (params.tokens.length != params.data.length) {\\n revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);\\n }\\n\\n OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);\\n\\n if (params.tokens.length == 0) {\\n return prices;\\n }\\n\\n uint256 maxPriceAge = forAtomicAction ? dataStore.getUint(Keys.MAX_ATOMIC_ORACLE_PRICE_AGE) : dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);\\n uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);\\n\\n for (uint256 i; i < params.tokens.length; i++) {\\n address _provider = params.providers[i];\\n IOracleProvider provider = IOracleProvider(_provider);\\n\\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(_provider))) {\\n revert Errors.InvalidOracleProvider(_provider);\\n }\\n\\n address token = params.tokens[i];\\n\\n bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(_provider));\\n\\n // if the action is atomic then only validate that the provider is an\\n // atomic provider\\n // else, validate that the provider matches the oracleProviderForToken\\n //\\n // since for atomic actions, any atomic provider can be used, it is\\n // recommended that only one atomic provider is configured per token\\n // otherwise there is a risk that if there is a difference in pricing\\n // between atomic oracle providers for a token, a user could use that\\n // to gain a profit by alternating actions between the two atomic\\n // providers\\n if (forAtomicAction) {\\n if (!isAtomicProvider) {\\n revert Errors.NonAtomicOracleProvider(_provider);\\n }\\n } else {\\n address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(address(this), token));\\n if (_provider != expectedProvider) {\\n revert Errors.InvalidOracleProviderForToken(_provider, expectedProvider);\\n }\\n }\\n\\n bytes memory data = params.data[i];\\n\\n OracleUtils.ValidatedPrice memory validatedPrice = provider.getOraclePrice(\\n token,\\n data\\n );\\n\\n // for atomic providers, the timestamp will be the current block's timestamp\\n // the timestamp should not be adjusted\\n if (provider.shouldAdjustTimestamp()) {\\n uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(_provider, token));\\n validatedPrice.timestamp -= timestampAdjustment;\\n }\\n\\n if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {\\n revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());\\n }\\n\\n if (!provider.isChainlinkOnChainProvider()) {\\n (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\\n\\n if (hasRefPrice) {\\n _validateRefPrice(\\n token,\\n validatedPrice.min,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n\\n _validateRefPrice(\\n token,\\n validatedPrice.max,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n prices[i] = validatedPrice;\\n }\\n\\n return prices;\\n }\\n\\n function _validateRefPrice(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n ) internal pure {\\n uint256 diff = Calc.diff(price, refPrice);\\n uint256 diffFactor = Precision.toFactor(diff, refPrice);\\n\\n if (diffFactor > maxRefPriceDeviationFactor) {\\n revert Errors.MaxRefPriceDeviationExceeded(\\n token,\\n price,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n function _setPrimaryPrice(address token, Price.Props memory price) internal {\\n if (price.min > price.max) {\\n revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);\\n }\\n\\n Price.Props memory existingPrice = primaryPrices[token];\\n\\n if (!existingPrice.isEmpty()) {\\n revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);\\n }\\n\\n primaryPrices[token] = price;\\n tokensWithPrices.add(token);\\n }\\n\\n function _removePrimaryPrice(address token) internal {\\n delete primaryPrices[token];\\n tokensWithPrices.remove(token);\\n }\\n\\n function _emitOraclePriceUpdated(\\n address token,\\n uint256 minPrice,\\n uint256 maxPrice,\\n uint256 timestamp,\\n address provider\\n ) internal {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"provider\\\", provider);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"minPrice\\\", minPrice);\\n eventData.uintItems.setItem(1, \\\"maxPrice\\\", maxPrice);\\n eventData.uintItems.setItem(2, \\\"timestamp\\\", timestamp);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OraclePriceUpdate\\\",\\n Cast.toBytes32(token),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x37cac3c6590c434acbf8b391b6a6fb875ecb671e2859f473d17d5afe7e1e38e5\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IOracle.sol\\\";\\n\\n// @title OracleModule\\n// @dev Provides convenience functions for interacting with the Oracle\\ncontract OracleModule {\\n IOracle public immutable oracle;\\n\\n constructor(IOracle _oracle) {\\n oracle = _oracle;\\n }\\n\\n // @dev sets oracle prices, perform any additional tasks required,\\n // and clear the oracle prices after\\n //\\n // care should be taken to avoid re-entrancy while using this call\\n // since re-entrancy could allow functions to be called with prices\\n // meant for a different type of transaction\\n // the tokensWithPrices.length check in oracle.setPrices should help\\n // mitigate this\\n //\\n // @param params OracleUtils.SetPricesParams\\n modifier withOraclePrices(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPrices(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n modifier withOraclePricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPricesForAtomicAction(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n // @dev set oracle prices for a simulation\\n // tokensWithPrices is not set in this function\\n // it is possible for withSimulatedOraclePrices to be called and a function\\n // using withOraclePrices to be called after\\n // or for a function using withOraclePrices to be called and withSimulatedOraclePrices\\n // called after\\n // this should not cause an issue because this transaction should always revert\\n // and any state changes based on simulated prices as well as the setting of simulated\\n // prices should not be persisted\\n // @param params OracleUtils.SimulatePricesParams\\n modifier withSimulatedOraclePrices(\\n OracleUtils.SimulatePricesParams memory params\\n ) {\\n if (params.primaryTokens.length != params.primaryPrices.length) {\\n revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);\\n }\\n\\n for (uint256 i; i < params.primaryTokens.length; i++) {\\n address token = params.primaryTokens[i];\\n Price.Props memory price = params.primaryPrices[i];\\n oracle.setPrimaryPrice(token, price);\\n }\\n\\n oracle.setTimestamps(params.minTimestamp, params.maxTimestamp);\\n\\n _;\\n\\n revert Errors.EndOfOracleSimulation();\\n }\\n}\\n\",\"keccak256\":\"0x19e4098e3f037bb6e1deb3a93aa98d42ceac46bf10553fb9aff784f9fbbc16ff\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\n// @title OracleStore\\n// @dev Stores the list of oracle signers\\ncontract OracleStore is RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n EventEmitter public immutable eventEmitter;\\n\\n EnumerableSet.AddressSet internal signers;\\n\\n constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {\\n eventEmitter = _eventEmitter;\\n }\\n\\n // @dev adds a signer\\n // @param account address of the signer to add\\n function addSigner(address account) external onlyController {\\n signers.add(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerAdded\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev removes a signer\\n // @param account address of the signer to remove\\n function removeSigner(address account) external onlyController {\\n signers.remove(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerRemoved\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev get the total number of signers\\n // @return the total number of signers\\n function getSignerCount() external view returns (uint256) {\\n return signers.length();\\n }\\n\\n // @dev get the signer at the specified index\\n // @param index the index of the signer to get\\n // @return the signer at the specified index\\n function getSigner(uint256 index) external view returns (address) {\\n return signers.at(index);\\n }\\n\\n // @dev get the signers for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the signers for the specified indexes\\n function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {\\n return signers.valuesAt(start, end);\\n }\\n}\\n\",\"keccak256\":\"0x5b9c2917e29aa696a8385f9f8b6a0cd0f1ef9a0b08d8096a2f19367e89cc09e7\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n // @dev IsPositionLiquidatableCache struct used in isPositionLiquidatable\\n // to avoid stack too deep errors\\n // @param positionPnlUsd the position's pnl in USD\\n // @param minCollateralFactor the min collateral factor\\n // @param collateralTokenPrice the collateral token price\\n // @param collateralUsd the position's collateral in USD\\n // @param usdDeltaForPriceImpact the usdDelta value for the price impact calculation\\n // @param priceImpactUsd the price impact of closing the position in USD\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n // @dev check if a position is liquidatable\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0x98416c7f41b0baf01552655c8034e98c71f204b6449fa967c44eb2df84391fab\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Uint256Mask.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary Uint256Mask {\\n struct Mask {\\n uint256 bits;\\n }\\n\\n function validateUniqueAndSetIndex(\\n Mask memory mask,\\n uint256 index,\\n string memory label\\n ) internal pure {\\n if (index >= 256) {\\n revert Errors.MaskIndexOutOfBounds(index, label);\\n }\\n\\n uint256 bit = 1 << index;\\n\\n if (mask.bits & bit != 0) {\\n revert Errors.DuplicatedIndex(index, label);\\n }\\n\\n mask.bits = mask.bits | bit;\\n }\\n}\\n\",\"keccak256\":\"0x96aaf43efa3a092b2d8d1e88addab6c31f5a7f526b84a290b9ba43e803592e01\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b50604051612b15380380612b1583398101604081905261002f916103e6565b828686863361004c600080516020612a958339815191528061020b565b610072600080516020612ab5833981519152600080516020612a9583398151915261020b565b610098600080516020612ad5833981519152600080516020612a9583398151915261020b565b6100be600080516020612af5833981519152600080516020612a9583398151915261020b565b6100d6600080516020612a9583398151915230610256565b6001600160a01b038116156100fd576100fd600080516020612a9583398151915282610256565b60005b835181101561016c57610140600080516020612ab583398151915285838151811061012d5761012d610494565b602002602001015161025660201b60201c565b610164600080516020612af583398151915285838151811061012d5761012d610494565b600101610100565b5060005b82518110156101a55761019d600080516020612ad583398151915284838151811061012d5761012d610494565b600101610170565b5060028490556040805160008152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a15050506001600160a01b039182166080525091821660a0521660c052506104aa92505050565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6102608282610264565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610260576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556102be3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461032d57600080fd5b50565b805161033b81610318565b919050565b600082601f83011261035157600080fd5b81516001600160401b0381111561036a5761036a610302565b604051600582901b90603f8201601f191681016001600160401b038111828210171561039857610398610302565b6040529182526020818501810192908101868411156103b657600080fd5b6020860192505b838310156103dc576103ce83610330565b8152602092830192016103bd565b5095945050505050565b60008060008060008060c087890312156103ff57600080fd5b865160208801519096506001600160401b0381111561041d57600080fd5b61042989828a01610340565b604089015190965090506001600160401b0381111561044757600080fd5b61045389828a01610340565b945050606087015161046481610318565b608088015190935061047581610318565b60a088015190925061048681610318565b809150509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c051612584610511600039600081816104df0152818161094c01526110820152600081816103dd0152818161092a01526110600152600081816104290152818161096e01528181610d8f01528181610e0601526110a401526125846000f3fe60806040526004361061018d5760003560e01c806301d5062a1461019957806301ffc9a7146101bb57806307bd0265146101f05780630d3cf6fc14610220578063134008d31461025457806313bc9f2014610267578063150b7a0214610287578063248a9ca3146102cb5780632ab0f529146102eb5780632f2ff15d1461030b57806331d507501461032b57806336568abe1461034b578063575d346a1461036b578063584b153e1461038b57806364d62353146103ab578063660d0d67146103cb5780637dc0d1d0146104175780638065657f1461044b5780638f2a0bb01461046b5780638f61f4f51461048b57806391d14854146104ad5780639ff78c30146104cd578063a217fddf14610501578063b08e51c014610516578063b1c5f42714610538578063bc197c8114610558578063c4d252f514610584578063d0663e61146105a4578063d45c4435146105c4578063d547741f146105e4578063e38335e514610604578063f128024b14610617578063f23a6e6114610637578063f27a0c921461066357600080fd5b3661019457005b600080fd5b3480156101a557600080fd5b506101b96101b43660046116f3565b610678565b005b3480156101c757600080fd5b506101db6101d6366004611767565b610718565b60405190151581526020015b60405180910390f35b3480156101fc57600080fd5b506102126000805160206124cf83398151915281565b6040519081526020016101e7565b34801561022c57600080fd5b506102127f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101b9610262366004611791565b610743565b34801561027357600080fd5b506101db6102823660046117fc565b6107d4565b34801561029357600080fd5b506102b26102a23660046118f2565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016101e7565b3480156102d757600080fd5b506102126102e63660046117fc565b6107f9565b3480156102f757600080fd5b506101db6103063660046117fc565b61080e565b34801561031757600080fd5b506101b9610326366004611959565b610822565b34801561033757600080fd5b506101db6103463660046117fc565b610843565b34801561035757600080fd5b506101b9610366366004611959565b610856565b34801561037757600080fd5b506101b9610386366004611985565b6108d9565b34801561039757600080fd5b506101db6103a63660046117fc565b6109d1565b3480156103b757600080fd5b506101b96103c63660046117fc565b6109de565b3480156103d757600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e7565b34801561042357600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045757600080fd5b50610212610466366004611791565b610a82565b34801561047757600080fd5b506101b9610486366004611a06565b610ac1565b34801561049757600080fd5b506102126000805160206124af83398151915281565b3480156104b957600080fd5b506101db6104c8366004611959565b610c16565b3480156104d957600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561050d57600080fd5b50610212600081565b34801561052257600080fd5b5061021260008051602061250f83398151915281565b34801561054457600080fd5b50610212610553366004611ac1565b610c3f565b34801561056457600080fd5b506102b2610573366004611c03565b63bc197c8160e01b95945050505050565b34801561059057600080fd5b506101b961059f3660046117fc565b610c84565b3480156105b057600080fd5b506101b96105bf366004611cb6565b610d47565b3480156105d057600080fd5b506102126105df3660046117fc565b610e81565b3480156105f057600080fd5b506101b96105ff366004611959565b610e93565b6101b9610612366004611ac1565b610eaf565b34801561062357600080fd5b506101b9610632366004611985565b61100f565b34801561064357600080fd5b506102b2610652366004611d57565b63f23a6e6160e01b95945050505050565b34801561066f57600080fd5b50600254610212565b6000805160206124af833981519152610690816110d2565b60006106a0898989898989610a82565b90506106ac81846110df565b6000816000805160206124ef8339815191528b8b8b8b8b8a6040516106d696959493929190611dd8565b60405180910390a3831561070d578060008051602061252f8339815191528560405161070491815260200190565b60405180910390a25b505050505050505050565b60006001600160e01b03198216630271189760e51b148061073d575061073d826111ce565b92915050565b6000805160206124cf83398151915261075d816000610c16565b61076b5761076b8133611203565b600061077b888888888888610a82565b9050610787818561125c565b610793888888886112ed565b60008160008051602061248f8339815191528a8a8a8a6040516107b99493929190611e15565b60405180910390a36107ca816113c0565b5050505050505050565b6000806107e083610e81565b90506001811180156107f25750428111155b9392505050565b60009081526020819052604090206001015490565b6000600161081b83610e81565b1492915050565b61082b826107f9565b610834816110d2565b61083e83836113f9565b505050565b60008061084f83610e81565b1192915050565b6001600160a01b03811633146108cb5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108d5828261147d565b5050565b3330146108fb573360405163a35b150b60e01b81526004016108c29190611e47565b604051630520f17f60e21b81527387a0d100b4F9b2A53353974c3596eEC33de8060f90631483c5fc9061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b60006040518083038186803b1580156109b457600080fd5b505af41580156109c8573d6000803e3d6000fd5b50505050505050565b6000600161084f83610e81565b333014610a415760405162461bcd60e51b815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201526a62652074696d656c6f636b60a81b60648201526084016108c2565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610a9f96959493929190611dd8565b6040516020818303038152906040528051906020012090509695505050505050565b6000805160206124af833981519152610ad9816110d2565b888714610af85760405162461bcd60e51b81526004016108c290611eb2565b888514610b175760405162461bcd60e51b81526004016108c290611eb2565b6000610b298b8b8b8b8b8b8b8b610c3f565b9050610b3581846110df565b60005b8a811015610bd95780826000805160206124ef8339815191528e8e85818110610b6357610b63611ef5565b9050602002016020810190610b789190611f0b565b8d8d86818110610b8a57610b8a611ef5565b905060200201358c8c87818110610ba357610ba3611ef5565b9050602002810190610bb59190611f26565b8c8b604051610bc996959493929190611dd8565b60405180910390a3600101610b38565b508315610c09578060008051602061252f83398151915285604051610c0091815260200190565b60405180910390a25b5050505050505050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008888888888888888604051602001610c60989796959493929190612005565b60405160208183030381529060405280519060200120905098975050505050505050565b60008051602061250f833981519152610c9c816110d2565b610ca5826109d1565b610d0b5760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e2063616044820152701b9b9bdd0818994818d85b98d95b1b1959607a1b60648201526084016108c2565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b6000805160206124cf833981519152610d61816000610c16565b610d6f57610d6f8133611203565b610d788261210b565b6040516331e999fd60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c7a667f490610dc49084906004016122b5565b600060405180830381600087803b158015610dde57600080fd5b505af1158015610df2573d6000803e3d6000fd5b50505050610e04898989898989610743565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662ccf1556040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e5e57600080fd5b505af1158015610e72573d6000803e3d6000fd5b50505050505050505050505050565b60009081526001602052604090205490565b610e9c826107f9565b610ea5816110d2565b61083e838361147d565b6000805160206124cf833981519152610ec9816000610c16565b610ed757610ed78133611203565b878614610ef65760405162461bcd60e51b81526004016108c290611eb2565b878414610f155760405162461bcd60e51b81526004016108c290611eb2565b6000610f278a8a8a8a8a8a8a8a610c3f565b9050610f33818561125c565b60005b89811015610ff95760008b8b83818110610f5257610f52611ef5565b9050602002016020810190610f679190611f0b565b905060008a8a84818110610f7d57610f7d611ef5565b9050602002013590503660008a8a86818110610f9b57610f9b611ef5565b9050602002810190610fad9190611f26565b91509150610fbd848484846112ed565b848660008051602061248f83398151915286868686604051610fe29493929190611e15565b60405180910390a350505050806001019050610f36565b50611003816113c0565b50505050505050505050565b333014611031573360405163a35b150b60e01b81526004016108c29190611e47565b604051639166d48160e01b81527387a0d100b4F9b2A53353974c3596eEC33de8060f90639166d4819061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b6110dc8133611203565b50565b6110e882610843565b1561114d5760405162461bcd60e51b815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201526e1c9958591e481cd8da19591d5b1959608a1b60648201526084016108c2565b6002548110156111ae5760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e746044820152652064656c617960d01b60648201526084016108c2565b6111b88142612371565b6000928352600160205260409092209190915550565b60006001600160e01b03198216637965db0b60e01b148061073d57506301ffc9a760e01b6001600160e01b031983161461073d565b61120d8282610c16565b6108d55761121a816114e2565b6112258360206114f4565b604051602001611236929190612384565b60408051601f198184030181529082905262461bcd60e51b82526108c2916004016123f3565b611265826107d4565b6112815760405162461bcd60e51b81526004016108c290612406565b80158061129257506112928161080e565b6108d55760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e6720646570656044820152656e64656e637960d01b60648201526084016108c2565b6000846001600160a01b031684848460405161130a929190612450565b60006040518083038185875af1925050503d8060008114611347576040519150601f19603f3d011682016040523d82523d6000602084013e61134c565b606091505b50509050806113b95760405162461bcd60e51b815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e6720746044820152721c985b9cd858dd1a5bdb881c995d995c9d1959606a1b60648201526084016108c2565b5050505050565b6113c9816107d4565b6113e55760405162461bcd60e51b81526004016108c290612406565b600090815260016020819052604090912055565b6114038282610c16565b6108d5576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556114393390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114878282610c16565b156108d5576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b606061073d6001600160a01b03831660145b60606000611503836002612460565b61150e906002612371565b6001600160401b0381111561152557611525611815565b6040519080825280601f01601f19166020018201604052801561154f576020820181803683370190505b509050600360fc1b8160008151811061156a5761156a611ef5565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061159957611599611ef5565b60200101906001600160f81b031916908160001a90535060006115bd846002612460565b6115c8906001612371565b90505b6001811115611640576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106115fc576115fc611ef5565b1a60f81b82828151811061161257611612611ef5565b60200101906001600160f81b031916908160001a90535060049490941c9361163981612477565b90506115cb565b5083156107f25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108c2565b80356001600160a01b03811681146116a657600080fd5b919050565b60008083601f8401126116bd57600080fd5b5081356001600160401b038111156116d457600080fd5b6020830191508360208285010111156116ec57600080fd5b9250929050565b600080600080600080600060c0888a03121561170e57600080fd5b6117178861168f565b96506020880135955060408801356001600160401b0381111561173957600080fd5b6117458a828b016116ab565b989b979a50986060810135976080820135975060a09091013595509350505050565b60006020828403121561177957600080fd5b81356001600160e01b0319811681146107f257600080fd5b60008060008060008060a087890312156117aa57600080fd5b6117b38761168f565b95506020870135945060408701356001600160401b038111156117d557600080fd5b6117e189828a016116ab565b979a9699509760608101359660809091013595509350505050565b60006020828403121561180e57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561184d5761184d611815565b60405290565b604051601f8201601f191681016001600160401b038111828210171561187b5761187b611815565b604052919050565b600082601f83011261189457600080fd5b81356001600160401b038111156118ad576118ad611815565b6118c0601f8201601f1916602001611853565b8181528460208386010111156118d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561190857600080fd5b6119118561168f565b935061191f6020860161168f565b92506040850135915060608501356001600160401b0381111561194157600080fd5b61194d87828801611883565b91505092959194509250565b6000806040838503121561196c57600080fd5b8235915061197c6020840161168f565b90509250929050565b60008060006060848603121561199a57600080fd5b6119a38461168f565b92506119b16020850161168f565b929592945050506040919091013590565b60008083601f8401126119d457600080fd5b5081356001600160401b038111156119eb57600080fd5b6020830191508360208260051b85010111156116ec57600080fd5b600080600080600080600080600060c08a8c031215611a2457600080fd5b89356001600160401b03811115611a3a57600080fd5b611a468c828d016119c2565b909a5098505060208a01356001600160401b03811115611a6557600080fd5b611a718c828d016119c2565b90985096505060408a01356001600160401b03811115611a9057600080fd5b611a9c8c828d016119c2565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b031215611add57600080fd5b88356001600160401b03811115611af357600080fd5b611aff8b828c016119c2565b90995097505060208901356001600160401b03811115611b1e57600080fd5b611b2a8b828c016119c2565b90975095505060408901356001600160401b03811115611b4957600080fd5b611b558b828c016119c2565b999c989b509699959896976060870135966080013595509350505050565b60006001600160401b03821115611b8c57611b8c611815565b5060051b60200190565b600082601f830112611ba757600080fd5b8135611bba611bb582611b73565b611853565b8082825260208201915060208360051b860101925085831115611bdc57600080fd5b602085015b83811015611bf9578035835260209283019201611be1565b5095945050505050565b600080600080600060a08688031215611c1b57600080fd5b611c248661168f565b9450611c326020870161168f565b935060408601356001600160401b03811115611c4d57600080fd5b611c5988828901611b96565b93505060608601356001600160401b03811115611c7557600080fd5b611c8188828901611b96565b92505060808601356001600160401b03811115611c9d57600080fd5b611ca988828901611883565b9150509295509295909350565b600080600080600080600060c0888a031215611cd157600080fd5b611cda8861168f565b96506020880135955060408801356001600160401b03811115611cfc57600080fd5b611d088a828b016116ab565b909650945050606088013592506080880135915060a08801356001600160401b03811115611d3557600080fd5b88016060818b031215611d4757600080fd5b8091505092959891949750929550565b600080600080600060a08688031215611d6f57600080fd5b611d788661168f565b9450611d866020870161168f565b9350604086013592506060860135915060808601356001600160401b03811115611c9d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201526000611e0060a083018688611daf565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201526000611e3d606083018486611daf565b9695505050505050565b6001600160a01b039190911681526040602082018190526004908201526329a2a62360e11b606082015260800190565b6001600160a01b039687168152948616602086015292851660408501529084166060840152909216608082015260a081019190915260c00190565b60208082526023908201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d616040820152620e8c6d60eb1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611f1d57600080fd5b6107f28261168f565b6000808335601e19843603018112611f3d57600080fd5b8301803591506001600160401b03821115611f5757600080fd5b6020019150368190038213156116ec57600080fd5b60008383855260208501945060208460051b8201018360005b86811015611ff957838303601f19018852813536879003601e19018112611fab57600080fd5b86016020810190356001600160401b03811115611fc757600080fd5b803603821315611fd657600080fd5b611fe1858284611daf565b60209a8b019a90955093909301925050600101611f85565b50909695505050505050565b60a0808252810188905260008960c08301825b8b811015612046576001600160a01b036120318461168f565b16825260209283019290910190600101612018565b5083810360208501528881526001600160fb1b0389111561206657600080fd5b8860051b9150818a6020830137018281036020908101604085015261208e9082018789611f6c565b60608401959095525050608001529695505050505050565b600082601f8301126120b757600080fd5b81356120c5611bb582611b73565b8082825260208201915060208360051b8601019250858311156120e757600080fd5b602085015b83811015611bf9576120fd8161168f565b8352602092830192016120ec565b60006060823603121561211d57600080fd5b61212561182b565b82356001600160401b0381111561213b57600080fd5b612147368286016120a6565b82525060208301356001600160401b0381111561216357600080fd5b61216f368286016120a6565b60208301525060408301356001600160401b0381111561218e57600080fd5b830136601f82011261219f57600080fd5b80356121ad611bb582611b73565b8082825260208201915060208360051b8501019250368311156121cf57600080fd5b602084015b838110156122105780356001600160401b038111156121f257600080fd5b61220136602083890101611883565b845250602092830192016121d4565b5060408501525091949350505050565b600081518084526020840193506020830160005b8281101561225b5781516001600160a01b0316865260209586019590910190600101612234565b5093949350505050565b60005b83811015612280578181015183820152602001612268565b50506000910152565b600081518084526122a1816020860160208601612265565b601f01601f19169290920160200192915050565b6020815260008251606060208401526122d16080840182612220565b90506020840151601f198483030160408501526122ee8282612220565b6040860151858203601f190160608701528051808352919350602090810192508084019190600582901b85010160005b8281101561234f57601f1986830301845261233a828651612289565b6020958601959490940193915060010161231e565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561073d5761073d61235b565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516123b6816017850160208801612265565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516123e7816028840160208801612265565b01602801949350505050565b6020815260006107f26020830184612289565b6020808252602a908201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e206973604082015269206e6f7420726561647960b01b606082015260800190565b8183823760009101908152919050565b808202811582820484141761073d5761073d61235b565b6000816124865761248661235b565b50600019019056fec2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e634cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dcafd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78320fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387a2646970667358221220fdb54e22e1201403a2fc00109344cfcc4bcff3ca2a418fe18652b436867c310564736f6c634300081d00335f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63fd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", - "deployedBytecode": "0x60806040526004361061018d5760003560e01c806301d5062a1461019957806301ffc9a7146101bb57806307bd0265146101f05780630d3cf6fc14610220578063134008d31461025457806313bc9f2014610267578063150b7a0214610287578063248a9ca3146102cb5780632ab0f529146102eb5780632f2ff15d1461030b57806331d507501461032b57806336568abe1461034b578063575d346a1461036b578063584b153e1461038b57806364d62353146103ab578063660d0d67146103cb5780637dc0d1d0146104175780638065657f1461044b5780638f2a0bb01461046b5780638f61f4f51461048b57806391d14854146104ad5780639ff78c30146104cd578063a217fddf14610501578063b08e51c014610516578063b1c5f42714610538578063bc197c8114610558578063c4d252f514610584578063d0663e61146105a4578063d45c4435146105c4578063d547741f146105e4578063e38335e514610604578063f128024b14610617578063f23a6e6114610637578063f27a0c921461066357600080fd5b3661019457005b600080fd5b3480156101a557600080fd5b506101b96101b43660046116f3565b610678565b005b3480156101c757600080fd5b506101db6101d6366004611767565b610718565b60405190151581526020015b60405180910390f35b3480156101fc57600080fd5b506102126000805160206124cf83398151915281565b6040519081526020016101e7565b34801561022c57600080fd5b506102127f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101b9610262366004611791565b610743565b34801561027357600080fd5b506101db6102823660046117fc565b6107d4565b34801561029357600080fd5b506102b26102a23660046118f2565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016101e7565b3480156102d757600080fd5b506102126102e63660046117fc565b6107f9565b3480156102f757600080fd5b506101db6103063660046117fc565b61080e565b34801561031757600080fd5b506101b9610326366004611959565b610822565b34801561033757600080fd5b506101db6103463660046117fc565b610843565b34801561035757600080fd5b506101b9610366366004611959565b610856565b34801561037757600080fd5b506101b9610386366004611985565b6108d9565b34801561039757600080fd5b506101db6103a63660046117fc565b6109d1565b3480156103b757600080fd5b506101b96103c63660046117fc565b6109de565b3480156103d757600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e7565b34801561042357600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045757600080fd5b50610212610466366004611791565b610a82565b34801561047757600080fd5b506101b9610486366004611a06565b610ac1565b34801561049757600080fd5b506102126000805160206124af83398151915281565b3480156104b957600080fd5b506101db6104c8366004611959565b610c16565b3480156104d957600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561050d57600080fd5b50610212600081565b34801561052257600080fd5b5061021260008051602061250f83398151915281565b34801561054457600080fd5b50610212610553366004611ac1565b610c3f565b34801561056457600080fd5b506102b2610573366004611c03565b63bc197c8160e01b95945050505050565b34801561059057600080fd5b506101b961059f3660046117fc565b610c84565b3480156105b057600080fd5b506101b96105bf366004611cb6565b610d47565b3480156105d057600080fd5b506102126105df3660046117fc565b610e81565b3480156105f057600080fd5b506101b96105ff366004611959565b610e93565b6101b9610612366004611ac1565b610eaf565b34801561062357600080fd5b506101b9610632366004611985565b61100f565b34801561064357600080fd5b506102b2610652366004611d57565b63f23a6e6160e01b95945050505050565b34801561066f57600080fd5b50600254610212565b6000805160206124af833981519152610690816110d2565b60006106a0898989898989610a82565b90506106ac81846110df565b6000816000805160206124ef8339815191528b8b8b8b8b8a6040516106d696959493929190611dd8565b60405180910390a3831561070d578060008051602061252f8339815191528560405161070491815260200190565b60405180910390a25b505050505050505050565b60006001600160e01b03198216630271189760e51b148061073d575061073d826111ce565b92915050565b6000805160206124cf83398151915261075d816000610c16565b61076b5761076b8133611203565b600061077b888888888888610a82565b9050610787818561125c565b610793888888886112ed565b60008160008051602061248f8339815191528a8a8a8a6040516107b99493929190611e15565b60405180910390a36107ca816113c0565b5050505050505050565b6000806107e083610e81565b90506001811180156107f25750428111155b9392505050565b60009081526020819052604090206001015490565b6000600161081b83610e81565b1492915050565b61082b826107f9565b610834816110d2565b61083e83836113f9565b505050565b60008061084f83610e81565b1192915050565b6001600160a01b03811633146108cb5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108d5828261147d565b5050565b3330146108fb573360405163a35b150b60e01b81526004016108c29190611e47565b604051630520f17f60e21b815273__$7cc2376e36274fcb28d593438dccae7b38$__90631483c5fc9061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b60006040518083038186803b1580156109b457600080fd5b505af41580156109c8573d6000803e3d6000fd5b50505050505050565b6000600161084f83610e81565b333014610a415760405162461bcd60e51b815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201526a62652074696d656c6f636b60a81b60648201526084016108c2565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610a9f96959493929190611dd8565b6040516020818303038152906040528051906020012090509695505050505050565b6000805160206124af833981519152610ad9816110d2565b888714610af85760405162461bcd60e51b81526004016108c290611eb2565b888514610b175760405162461bcd60e51b81526004016108c290611eb2565b6000610b298b8b8b8b8b8b8b8b610c3f565b9050610b3581846110df565b60005b8a811015610bd95780826000805160206124ef8339815191528e8e85818110610b6357610b63611ef5565b9050602002016020810190610b789190611f0b565b8d8d86818110610b8a57610b8a611ef5565b905060200201358c8c87818110610ba357610ba3611ef5565b9050602002810190610bb59190611f26565b8c8b604051610bc996959493929190611dd8565b60405180910390a3600101610b38565b508315610c09578060008051602061252f83398151915285604051610c0091815260200190565b60405180910390a25b5050505050505050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008888888888888888604051602001610c60989796959493929190612005565b60405160208183030381529060405280519060200120905098975050505050505050565b60008051602061250f833981519152610c9c816110d2565b610ca5826109d1565b610d0b5760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e2063616044820152701b9b9bdd0818994818d85b98d95b1b1959607a1b60648201526084016108c2565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b6000805160206124cf833981519152610d61816000610c16565b610d6f57610d6f8133611203565b610d788261210b565b6040516331e999fd60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c7a667f490610dc49084906004016122b5565b600060405180830381600087803b158015610dde57600080fd5b505af1158015610df2573d6000803e3d6000fd5b50505050610e04898989898989610743565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662ccf1556040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e5e57600080fd5b505af1158015610e72573d6000803e3d6000fd5b50505050505050505050505050565b60009081526001602052604090205490565b610e9c826107f9565b610ea5816110d2565b61083e838361147d565b6000805160206124cf833981519152610ec9816000610c16565b610ed757610ed78133611203565b878614610ef65760405162461bcd60e51b81526004016108c290611eb2565b878414610f155760405162461bcd60e51b81526004016108c290611eb2565b6000610f278a8a8a8a8a8a8a8a610c3f565b9050610f33818561125c565b60005b89811015610ff95760008b8b83818110610f5257610f52611ef5565b9050602002016020810190610f679190611f0b565b905060008a8a84818110610f7d57610f7d611ef5565b9050602002013590503660008a8a86818110610f9b57610f9b611ef5565b9050602002810190610fad9190611f26565b91509150610fbd848484846112ed565b848660008051602061248f83398151915286868686604051610fe29493929190611e15565b60405180910390a350505050806001019050610f36565b50611003816113c0565b50505050505050505050565b333014611031573360405163a35b150b60e01b81526004016108c29190611e47565b604051639166d48160e01b815273__$7cc2376e36274fcb28d593438dccae7b38$__90639166d4819061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b6110dc8133611203565b50565b6110e882610843565b1561114d5760405162461bcd60e51b815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201526e1c9958591e481cd8da19591d5b1959608a1b60648201526084016108c2565b6002548110156111ae5760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e746044820152652064656c617960d01b60648201526084016108c2565b6111b88142612371565b6000928352600160205260409092209190915550565b60006001600160e01b03198216637965db0b60e01b148061073d57506301ffc9a760e01b6001600160e01b031983161461073d565b61120d8282610c16565b6108d55761121a816114e2565b6112258360206114f4565b604051602001611236929190612384565b60408051601f198184030181529082905262461bcd60e51b82526108c2916004016123f3565b611265826107d4565b6112815760405162461bcd60e51b81526004016108c290612406565b80158061129257506112928161080e565b6108d55760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e6720646570656044820152656e64656e637960d01b60648201526084016108c2565b6000846001600160a01b031684848460405161130a929190612450565b60006040518083038185875af1925050503d8060008114611347576040519150601f19603f3d011682016040523d82523d6000602084013e61134c565b606091505b50509050806113b95760405162461bcd60e51b815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e6720746044820152721c985b9cd858dd1a5bdb881c995d995c9d1959606a1b60648201526084016108c2565b5050505050565b6113c9816107d4565b6113e55760405162461bcd60e51b81526004016108c290612406565b600090815260016020819052604090912055565b6114038282610c16565b6108d5576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556114393390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114878282610c16565b156108d5576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b606061073d6001600160a01b03831660145b60606000611503836002612460565b61150e906002612371565b6001600160401b0381111561152557611525611815565b6040519080825280601f01601f19166020018201604052801561154f576020820181803683370190505b509050600360fc1b8160008151811061156a5761156a611ef5565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061159957611599611ef5565b60200101906001600160f81b031916908160001a90535060006115bd846002612460565b6115c8906001612371565b90505b6001811115611640576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106115fc576115fc611ef5565b1a60f81b82828151811061161257611612611ef5565b60200101906001600160f81b031916908160001a90535060049490941c9361163981612477565b90506115cb565b5083156107f25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108c2565b80356001600160a01b03811681146116a657600080fd5b919050565b60008083601f8401126116bd57600080fd5b5081356001600160401b038111156116d457600080fd5b6020830191508360208285010111156116ec57600080fd5b9250929050565b600080600080600080600060c0888a03121561170e57600080fd5b6117178861168f565b96506020880135955060408801356001600160401b0381111561173957600080fd5b6117458a828b016116ab565b989b979a50986060810135976080820135975060a09091013595509350505050565b60006020828403121561177957600080fd5b81356001600160e01b0319811681146107f257600080fd5b60008060008060008060a087890312156117aa57600080fd5b6117b38761168f565b95506020870135945060408701356001600160401b038111156117d557600080fd5b6117e189828a016116ab565b979a9699509760608101359660809091013595509350505050565b60006020828403121561180e57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561184d5761184d611815565b60405290565b604051601f8201601f191681016001600160401b038111828210171561187b5761187b611815565b604052919050565b600082601f83011261189457600080fd5b81356001600160401b038111156118ad576118ad611815565b6118c0601f8201601f1916602001611853565b8181528460208386010111156118d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561190857600080fd5b6119118561168f565b935061191f6020860161168f565b92506040850135915060608501356001600160401b0381111561194157600080fd5b61194d87828801611883565b91505092959194509250565b6000806040838503121561196c57600080fd5b8235915061197c6020840161168f565b90509250929050565b60008060006060848603121561199a57600080fd5b6119a38461168f565b92506119b16020850161168f565b929592945050506040919091013590565b60008083601f8401126119d457600080fd5b5081356001600160401b038111156119eb57600080fd5b6020830191508360208260051b85010111156116ec57600080fd5b600080600080600080600080600060c08a8c031215611a2457600080fd5b89356001600160401b03811115611a3a57600080fd5b611a468c828d016119c2565b909a5098505060208a01356001600160401b03811115611a6557600080fd5b611a718c828d016119c2565b90985096505060408a01356001600160401b03811115611a9057600080fd5b611a9c8c828d016119c2565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b031215611add57600080fd5b88356001600160401b03811115611af357600080fd5b611aff8b828c016119c2565b90995097505060208901356001600160401b03811115611b1e57600080fd5b611b2a8b828c016119c2565b90975095505060408901356001600160401b03811115611b4957600080fd5b611b558b828c016119c2565b999c989b509699959896976060870135966080013595509350505050565b60006001600160401b03821115611b8c57611b8c611815565b5060051b60200190565b600082601f830112611ba757600080fd5b8135611bba611bb582611b73565b611853565b8082825260208201915060208360051b860101925085831115611bdc57600080fd5b602085015b83811015611bf9578035835260209283019201611be1565b5095945050505050565b600080600080600060a08688031215611c1b57600080fd5b611c248661168f565b9450611c326020870161168f565b935060408601356001600160401b03811115611c4d57600080fd5b611c5988828901611b96565b93505060608601356001600160401b03811115611c7557600080fd5b611c8188828901611b96565b92505060808601356001600160401b03811115611c9d57600080fd5b611ca988828901611883565b9150509295509295909350565b600080600080600080600060c0888a031215611cd157600080fd5b611cda8861168f565b96506020880135955060408801356001600160401b03811115611cfc57600080fd5b611d088a828b016116ab565b909650945050606088013592506080880135915060a08801356001600160401b03811115611d3557600080fd5b88016060818b031215611d4757600080fd5b8091505092959891949750929550565b600080600080600060a08688031215611d6f57600080fd5b611d788661168f565b9450611d866020870161168f565b9350604086013592506060860135915060808601356001600160401b03811115611c9d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201526000611e0060a083018688611daf565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201526000611e3d606083018486611daf565b9695505050505050565b6001600160a01b039190911681526040602082018190526004908201526329a2a62360e11b606082015260800190565b6001600160a01b039687168152948616602086015292851660408501529084166060840152909216608082015260a081019190915260c00190565b60208082526023908201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d616040820152620e8c6d60eb1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611f1d57600080fd5b6107f28261168f565b6000808335601e19843603018112611f3d57600080fd5b8301803591506001600160401b03821115611f5757600080fd5b6020019150368190038213156116ec57600080fd5b60008383855260208501945060208460051b8201018360005b86811015611ff957838303601f19018852813536879003601e19018112611fab57600080fd5b86016020810190356001600160401b03811115611fc757600080fd5b803603821315611fd657600080fd5b611fe1858284611daf565b60209a8b019a90955093909301925050600101611f85565b50909695505050505050565b60a0808252810188905260008960c08301825b8b811015612046576001600160a01b036120318461168f565b16825260209283019290910190600101612018565b5083810360208501528881526001600160fb1b0389111561206657600080fd5b8860051b9150818a6020830137018281036020908101604085015261208e9082018789611f6c565b60608401959095525050608001529695505050505050565b600082601f8301126120b757600080fd5b81356120c5611bb582611b73565b8082825260208201915060208360051b8601019250858311156120e757600080fd5b602085015b83811015611bf9576120fd8161168f565b8352602092830192016120ec565b60006060823603121561211d57600080fd5b61212561182b565b82356001600160401b0381111561213b57600080fd5b612147368286016120a6565b82525060208301356001600160401b0381111561216357600080fd5b61216f368286016120a6565b60208301525060408301356001600160401b0381111561218e57600080fd5b830136601f82011261219f57600080fd5b80356121ad611bb582611b73565b8082825260208201915060208360051b8501019250368311156121cf57600080fd5b602084015b838110156122105780356001600160401b038111156121f257600080fd5b61220136602083890101611883565b845250602092830192016121d4565b5060408501525091949350505050565b600081518084526020840193506020830160005b8281101561225b5781516001600160a01b0316865260209586019590910190600101612234565b5093949350505050565b60005b83811015612280578181015183820152602001612268565b50506000910152565b600081518084526122a1816020860160208601612265565b601f01601f19169290920160200192915050565b6020815260008251606060208401526122d16080840182612220565b90506020840151601f198483030160408501526122ee8282612220565b6040860151858203601f190160608701528051808352919350602090810192508084019190600582901b85010160005b8281101561234f57601f1986830301845261233a828651612289565b6020958601959490940193915060010161231e565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561073d5761073d61235b565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516123b6816017850160208801612265565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516123e7816028840160208801612265565b01602801949350505050565b6020815260006107f26020830184612289565b6020808252602a908201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e206973604082015269206e6f7420726561647960b01b606082015260800190565b8183823760009101908152919050565b808202811582820484141761073d5761073d61235b565b6000816124865761248661235b565b50600019019056fec2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e634cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dcafd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78320fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387a2646970667358221220fdb54e22e1201403a2fc00109344cfcc4bcff3ca2a418fe18652b436867c310564736f6c634300081d0033", + "numDeployments": 5, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minDelay\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"proposers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"executors\",\"type\":\"address[]\"},{\"internalType\":\"contract Oracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"contract DataStore\",\"name\":\"_dataStore\",\"type\":\"address\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"_eventEmitter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"role\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"CallExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"CallSalt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"CallScheduled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"Cancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldDuration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newDuration\",\"type\":\"uint256\"}],\"name\":\"MinDelayChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CANCELLER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXECUTOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TIMELOCK_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dataStore\",\"outputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventEmitter\",\"outputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"providers\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct OracleUtils.SetPricesParams\",\"name\":\"oracleParams\",\"type\":\"tuple\"}],\"name\":\"executeWithOraclePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMinDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"hashOperation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"hashOperationBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationDone\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationReady\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract IOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fundingAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"reductionAmount\",\"type\":\"uint256\"}],\"name\":\"reduceLentImpactAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"schedule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"scheduleBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newDelay\",\"type\":\"uint256\"}],\"name\":\"updateDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFromPositionImpactPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"CallExecuted(bytes32,uint256,address,uint256,bytes)\":{\"details\":\"Emitted when a call is performed as part of operation `id`.\"},\"CallSalt(bytes32,bytes32)\":{\"details\":\"Emitted when new proposal is scheduled with non-zero salt.\"},\"CallScheduled(bytes32,uint256,address,uint256,bytes,bytes32,uint256)\":{\"details\":\"Emitted when a call is scheduled as part of operation `id`.\"},\"Cancelled(bytes32)\":{\"details\":\"Emitted when operation `id` is cancelled.\"},\"MinDelayChange(uint256,uint256)\":{\"details\":\"Emitted when the minimum delay for future operations is modified.\"},\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"cancel(bytes32)\":{\"details\":\"Cancel an operation. Requirements: - the caller must have the 'canceller' role.\"},\"execute(address,uint256,bytes,bytes32,bytes32)\":{\"details\":\"Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements: - the caller must have the 'executor' role.\"},\"executeBatch(address[],uint256[],bytes[],bytes32,bytes32)\":{\"details\":\"Execute an (ready) operation containing a batch of transactions. Emits one {CallExecuted} event per transaction in the batch. Requirements: - the caller must have the 'executor' role.\"},\"getMinDelay()\":{\"details\":\"Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls `updateDelay`.\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getTimestamp(bytes32)\":{\"details\":\"Returns the timestamp at which an operation becomes ready (0 for unset operations, 1 for done operations).\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"hashOperation(address,uint256,bytes,bytes32,bytes32)\":{\"details\":\"Returns the identifier of an operation containing a single transaction.\"},\"hashOperationBatch(address[],uint256[],bytes[],bytes32,bytes32)\":{\"details\":\"Returns the identifier of an operation containing a batch of transactions.\"},\"isOperation(bytes32)\":{\"details\":\"Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.\"},\"isOperationDone(bytes32)\":{\"details\":\"Returns whether an operation is done or not.\"},\"isOperationPending(bytes32)\":{\"details\":\"Returns whether an operation is pending or not. Note that a \\\"pending\\\" operation may also be \\\"ready\\\".\"},\"isOperationReady(bytes32)\":{\"details\":\"Returns whether an operation is ready for execution. Note that a \\\"ready\\\" operation is also \\\"pending\\\".\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155BatchReceived}.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155Receiver-onERC1155Received}.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"schedule(address,uint256,bytes,bytes32,bytes32,uint256)\":{\"details\":\"Schedule an operation containing a single transaction. Emits {CallSalt} if salt is nonzero, and {CallScheduled}. Requirements: - the caller must have the 'proposer' role.\"},\"scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)\":{\"details\":\"Schedule an operation containing a batch of transactions. Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch. Requirements: - the caller must have the 'proposer' role.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateDelay(uint256)\":{\"details\":\"Changes the minimum timelock duration for future operations. Emits a {MinDelayChange} event. Requirements: - the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/config/ConfigTimelockController.sol\":\"ConfigTimelockController\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorInterface {\\n function latestAnswer() external view returns (int256);\\n\\n function latestTimestamp() external view returns (uint256);\\n\\n function latestRound() external view returns (uint256);\\n\\n function getAnswer(uint256 roundId) external view returns (int256);\\n\\n function getTimestamp(uint256 roundId) external view returns (uint256);\\n\\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\\n\\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\\n}\\n\",\"keccak256\":\"0xb496651006b9a2a07920ffe116928b11e2a6458e21361cecca51409522488ca7\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {AggregatorInterface} from \\\"./AggregatorInterface.sol\\\";\\nimport {AggregatorV3Interface} from \\\"./AggregatorV3Interface.sol\\\";\\n\\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\\n\",\"keccak256\":\"0xee12d80dbdbb3cc0ec10372b9323e42fae9a6de45da5a4e9f7a75223a0b5268b\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n function getRoundData(\\n uint80 _roundId\\n ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n\\n function latestRoundData()\\n external\\n view\\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n}\\n\",\"keccak256\":\"0xfe4e8bb4861bb3860ba890ab91a3b818ec66e5a8f544fb608cfcb73f433472cd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```solidity\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```solidity\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\\n * to enforce additional security measures for this role.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role);\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\\n * Overriding this function changes the behavior of the {onlyRole} modifier.\\n *\\n * Format of the revert message is described in {_checkRole}.\\n *\\n * _Available since v4.6._\\n */\\n function _checkRole(bytes32 role) internal view virtual {\\n _checkRole(role, _msgSender());\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view virtual {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(account),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * May emit a {RoleGranted} event.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n *\\n * NOTE: This function is deprecated in favor of {_grantRole}.\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n bytes32 previousAdminRole = getRoleAdmin(role);\\n _roles[role].adminRole = adminRole;\\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function _grantRole(bytes32 role, address account) internal virtual {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function _revokeRole(bytes32 role, address account) internal virtual {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0dd6e52cb394d7f5abe5dca2d4908a6be40417914720932de757de34a99ab87f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/governance/TimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../access/AccessControl.sol\\\";\\nimport \\\"../token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"../token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Contract module which acts as a timelocked controller. When set as the\\n * owner of an `Ownable` smart contract, it enforces a timelock on all\\n * `onlyOwner` maintenance operations. This gives time for users of the\\n * controlled contract to exit before a potentially dangerous maintenance\\n * operation is applied.\\n *\\n * By default, this contract is self administered, meaning administration tasks\\n * have to go through the timelock process. The proposer (resp executor) role\\n * is in charge of proposing (resp executing) operations. A common use case is\\n * to position this {TimelockController} as the owner of a smart contract, with\\n * a multisig or a DAO as the sole proposer.\\n *\\n * _Available since v3.3._\\n */\\ncontract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {\\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\\\"TIMELOCK_ADMIN_ROLE\\\");\\n bytes32 public constant PROPOSER_ROLE = keccak256(\\\"PROPOSER_ROLE\\\");\\n bytes32 public constant EXECUTOR_ROLE = keccak256(\\\"EXECUTOR_ROLE\\\");\\n bytes32 public constant CANCELLER_ROLE = keccak256(\\\"CANCELLER_ROLE\\\");\\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\\n\\n mapping(bytes32 => uint256) private _timestamps;\\n uint256 private _minDelay;\\n\\n /**\\n * @dev Emitted when a call is scheduled as part of operation `id`.\\n */\\n event CallScheduled(\\n bytes32 indexed id,\\n uint256 indexed index,\\n address target,\\n uint256 value,\\n bytes data,\\n bytes32 predecessor,\\n uint256 delay\\n );\\n\\n /**\\n * @dev Emitted when a call is performed as part of operation `id`.\\n */\\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\\n\\n /**\\n * @dev Emitted when new proposal is scheduled with non-zero salt.\\n */\\n event CallSalt(bytes32 indexed id, bytes32 salt);\\n\\n /**\\n * @dev Emitted when operation `id` is cancelled.\\n */\\n event Cancelled(bytes32 indexed id);\\n\\n /**\\n * @dev Emitted when the minimum delay for future operations is modified.\\n */\\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\\n\\n /**\\n * @dev Initializes the contract with the following parameters:\\n *\\n * - `minDelay`: initial minimum delay for operations\\n * - `proposers`: accounts to be granted proposer and canceller roles\\n * - `executors`: accounts to be granted executor role\\n * - `admin`: optional account to be granted admin role; disable with zero address\\n *\\n * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment\\n * without being subject to delay, but this role should be subsequently renounced in favor of\\n * administration through timelocked proposals. Previous versions of this contract would assign\\n * this admin to the deployer automatically and should be renounced as well.\\n */\\n constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {\\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);\\n\\n // self administration\\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\\n\\n // optional admin\\n if (admin != address(0)) {\\n _setupRole(TIMELOCK_ADMIN_ROLE, admin);\\n }\\n\\n // register proposers and cancellers\\n for (uint256 i = 0; i < proposers.length; ++i) {\\n _setupRole(PROPOSER_ROLE, proposers[i]);\\n _setupRole(CANCELLER_ROLE, proposers[i]);\\n }\\n\\n // register executors\\n for (uint256 i = 0; i < executors.length; ++i) {\\n _setupRole(EXECUTOR_ROLE, executors[i]);\\n }\\n\\n _minDelay = minDelay;\\n emit MinDelayChange(0, minDelay);\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only by a certain role. In\\n * addition to checking the sender's role, `address(0)` 's role is also\\n * considered. Granting a role to `address(0)` is equivalent to enabling\\n * this role for everyone.\\n */\\n modifier onlyRoleOrOpenRole(bytes32 role) {\\n if (!hasRole(role, address(0))) {\\n _checkRole(role, _msgSender());\\n }\\n _;\\n }\\n\\n /**\\n * @dev Contract might receive/hold ETH as part of the maintenance process.\\n */\\n receive() external payable {}\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns whether an id correspond to a registered operation. This\\n * includes both Pending, Ready and Done operations.\\n */\\n function isOperation(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > 0;\\n }\\n\\n /**\\n * @dev Returns whether an operation is pending or not. Note that a \\\"pending\\\" operation may also be \\\"ready\\\".\\n */\\n function isOperationPending(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns whether an operation is ready for execution. Note that a \\\"ready\\\" operation is also \\\"pending\\\".\\n */\\n function isOperationReady(bytes32 id) public view virtual returns (bool) {\\n uint256 timestamp = getTimestamp(id);\\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\\n }\\n\\n /**\\n * @dev Returns whether an operation is done or not.\\n */\\n function isOperationDone(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) == _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns the timestamp at which an operation becomes ready (0 for\\n * unset operations, 1 for done operations).\\n */\\n function getTimestamp(bytes32 id) public view virtual returns (uint256) {\\n return _timestamps[id];\\n }\\n\\n /**\\n * @dev Returns the minimum delay for an operation to become valid.\\n *\\n * This value can be changed by executing an operation that calls `updateDelay`.\\n */\\n function getMinDelay() public view virtual returns (uint256) {\\n return _minDelay;\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a single\\n * transaction.\\n */\\n function hashOperation(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(target, value, data, predecessor, salt));\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a batch of\\n * transactions.\\n */\\n function hashOperationBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(targets, values, payloads, predecessor, salt));\\n }\\n\\n /**\\n * @dev Schedule an operation containing a single transaction.\\n *\\n * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function schedule(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\\n _schedule(id, delay);\\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation containing a batch of transactions.\\n *\\n * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function scheduleBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n _schedule(id, delay);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);\\n }\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation that is to become valid after a given delay.\\n */\\n function _schedule(bytes32 id, uint256 delay) private {\\n require(!isOperation(id), \\\"TimelockController: operation already scheduled\\\");\\n require(delay >= getMinDelay(), \\\"TimelockController: insufficient delay\\\");\\n _timestamps[id] = block.timestamp + delay;\\n }\\n\\n /**\\n * @dev Cancel an operation.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'canceller' role.\\n */\\n function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {\\n require(isOperationPending(id), \\\"TimelockController: operation cannot be cancelled\\\");\\n delete _timestamps[id];\\n\\n emit Cancelled(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a single transaction.\\n *\\n * Emits a {CallExecuted} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function execute(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n bytes32 id = hashOperation(target, value, payload, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n _execute(target, value, payload);\\n emit CallExecuted(id, 0, target, value, payload);\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a batch of transactions.\\n *\\n * Emits one {CallExecuted} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n address target = targets[i];\\n uint256 value = values[i];\\n bytes calldata payload = payloads[i];\\n _execute(target, value, payload);\\n emit CallExecuted(id, i, target, value, payload);\\n }\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an operation's call.\\n */\\n function _execute(address target, uint256 value, bytes calldata data) internal virtual {\\n (bool success, ) = target.call{value: value}(data);\\n require(success, \\\"TimelockController: underlying transaction reverted\\\");\\n }\\n\\n /**\\n * @dev Checks before execution of an operation's calls.\\n */\\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \\\"TimelockController: missing dependency\\\");\\n }\\n\\n /**\\n * @dev Checks after execution of an operation's calls.\\n */\\n function _afterCall(bytes32 id) private {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n _timestamps[id] = _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Changes the minimum timelock duration for future operations.\\n *\\n * Emits a {MinDelayChange} event.\\n *\\n * Requirements:\\n *\\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\\n */\\n function updateDelay(uint256 newDelay) external virtual {\\n require(msg.sender == address(this), \\\"TimelockController: caller must be timelock\\\");\\n emit MinDelayChange(_minDelay, newDelay);\\n _minDelay = newDelay;\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xda2a70247fda81633d9392f567a401c4772837de6b0543c1c561ca632a2fe7f4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/config/ConfigTimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {EventUtils} from \\\"../event/EventUtils.sol\\\";\\nimport {Multicall3} from \\\"../mock/Multicall3.sol\\\";\\nimport {OracleStore} from \\\"../oracle/OracleStore.sol\\\";\\nimport {RoleStore} from \\\"../role/RoleStore.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {TimelockController} from \\\"@openzeppelin/contracts/governance/TimelockController.sol\\\";\\nimport {OracleModule} from \\\"../oracle/OracleModule.sol\\\";\\nimport {OracleUtils} from \\\"../oracle/OracleUtils.sol\\\";\\nimport {Oracle} from \\\"../oracle/Oracle.sol\\\";\\nimport {PositionImpactPoolUtils} from \\\"../market/PositionImpactPoolUtils.sol\\\";\\nimport {Chain} from \\\"../chain/Chain.sol\\\";\\nimport {AccountUtils} from \\\"../utils/AccountUtils.sol\\\";\\n\\ncontract ConfigTimelockController is TimelockController, OracleModule {\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n\\n constructor(\\n uint256 minDelay,\\n address[] memory proposers,\\n address[] memory executors,\\n Oracle oracle,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter\\n ) TimelockController(minDelay, proposers, executors, msg.sender) OracleModule(oracle) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n }\\n\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n // note that if on-chain prices are used for market operations, there may\\n // be some difference in pricing between the on-chain price and e.g.\\n // an off-chain data stream price\\n // it should be ensured that the changes to the market token price that\\n // result from this execution are not too large that it would lead to\\n // significant arbitrage opportunities\\n function executeWithOraclePrices(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt,\\n OracleUtils.SetPricesParams calldata oracleParams\\n ) external onlyRoleOrOpenRole(EXECUTOR_ROLE) withOraclePricesForAtomicAction(oracleParams) {\\n execute(target, value, payload, predecessor, salt);\\n }\\n\\n function withdrawFromPositionImpactPool(\\n address market,\\n address receiver,\\n uint256 amount\\n ) external onlySelf {\\n PositionImpactPoolUtils.withdrawFromPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentImpactAmount(\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external onlySelf {\\n PositionImpactPoolUtils.reduceLentAmount(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n fundingAccount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xfd4e8cf25c70dc3e8b14f59067edbacd134a7e3a1294250f7b0392049b51ddbf\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/market/PositionImpactPoolUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {Market} from \\\"./Market.sol\\\";\\nimport {MarketEventUtils} from \\\"./MarketEventUtils.sol\\\";\\nimport {MarketPoolValueInfo} from \\\"./MarketPoolValueInfo.sol\\\";\\nimport {MarketStoreUtils} from \\\"./MarketStoreUtils.sol\\\";\\nimport {MarketToken} from \\\"./MarketToken.sol\\\";\\nimport {MarketUtils} from \\\"./MarketUtils.sol\\\";\\nimport {SafeCast} from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IOracle } from \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../position/PositionUtils.sol\\\";\\n\\nlibrary PositionImpactPoolUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n using SafeERC20 for IERC20;\\n\\n using Market for Market.Props;\\n\\n // @dev withdraw funds from the position impact pool while maintaining GM token price\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param receiver the address to receive the withdrawn funds\\n // @param amount the amount to withdraw\\n // @param oracle - oracle to fetch the market prices\\n function withdrawFromPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n require(amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n MarketUtils.distributePositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market\\n );\\n\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\\n dataStore,\\n marketProps,\\n prices.indexTokenPrice,\\n prices.longTokenPrice,\\n prices.shortTokenPrice,\\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\\n false\\n );\\n\\n if (poolValueInfo.poolValue <= 0) {\\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\\n }\\n\\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\\n\\n // if there is a positive totalPendingImpactAmount, that means that the\\n // excess should be covered by the position impact pool, so subtract this\\n // from the impactPoolAmount that can be withdrawn\\n // lent amount is not considered here, because if there is a lent amount\\n // we assume that the position impact would be zero\\n if (totalPendingImpactAmount > 0) {\\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\\n }\\n\\n if (adjustedImpactPoolAmount < amount) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n MarketUtils.applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n - amount.toInt256()\\n );\\n\\n // Calculate amount of tokens to withdraw:\\n // We want to withdraw long and short tokens from the pool\\n // at the current pool token ratio\\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\\n dataStore,\\n marketProps,\\n prices,\\n amount * prices.indexTokenPrice.min\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n - longTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n - shortTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.longToken,\\n receiver,\\n longTokenWithdrawalAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.shortToken,\\n receiver,\\n shortTokenWithdrawalAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\\n eventEmitter,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external {\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\\n\\n if (reductionAmount > lentAmount) {\\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\\n }\\n\\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\\n\\n if (longTokenAmount > 0) {\\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\\n }\\n\\n if (shortTokenAmount > 0) {\\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\\n }\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n longTokenAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n shortTokenAmount.toInt256()\\n );\\n\\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitLentImpactAmountReduction(\\n eventEmitter,\\n market,\\n fundingAccount,\\n longTokenAmount,\\n shortTokenAmount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe74b2dfdd27d92eb33535d5c5fe4af456d05c180d17d8252f5728c62dd1293b0\",\"license\":\"BUSL-1.1\"},\"contracts/mock/Multicall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title Multicall3\\n/// @notice Aggregate results from multiple function calls\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract Multicall3 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked { valAccumulator += val; }\\n (result.success, result.returnData) = calli.target.call{value: val}(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked { ++i; }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x403295008f09f7f5911396b6243d95bd4084e8f6e085af2b958a4af64c29e07c\",\"license\":\"MIT\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/ChainlinkPriceFeedUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./IPriceFeed.sol\\\";\\n\\n// @title ChainlinkPriceFeedProviderUtils\\n// @dev Library for Chainlink price feed\\nlibrary ChainlinkPriceFeedUtils {\\n // there is a small risk of stale pricing due to latency in price updates or if the chain is down\\n // this is meant to be for temporary use until low latency price feeds are supported for all tokens\\n function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {\\n address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));\\n if (priceFeedAddress == address(0)) {\\n return (false, 0);\\n }\\n\\n IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);\\n\\n (\\n /* uint80 roundID */,\\n int256 _price,\\n /* uint256 startedAt */,\\n uint256 timestamp,\\n /* uint80 answeredInRound */\\n ) = priceFeed.latestRoundData();\\n\\n if (_price <= 0) {\\n revert Errors.InvalidFeedPrice(token, _price);\\n }\\n\\n uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));\\n if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {\\n revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);\\n }\\n\\n uint256 price = SafeCast.toUint256(_price);\\n uint256 precision = getPriceFeedMultiplier(dataStore, token);\\n\\n uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);\\n\\n return (true, adjustedPrice);\\n }\\n\\n // @dev get the multiplier value to convert the external price feed price to the price of 1 unit of the token\\n // represented with 30 decimals\\n // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of\\n // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)\\n // if the external price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8)\\n // in this case the priceFeedMultiplier should be 10 ^ 46\\n // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24)\\n // formula for decimals for price feed multiplier: 60 - (external price feed decimals) - (token decimals)\\n //\\n // @param dataStore DataStore\\n // @param token the token to get the price feed multiplier for\\n // @return the price feed multipler\\n function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {\\n uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));\\n\\n if (multiplier == 0) {\\n revert Errors.EmptyChainlinkPriceFeedMultiplier(token);\\n }\\n\\n return multiplier;\\n }\\n}\\n\",\"keccak256\":\"0xf2abeec57d21410a8306356562077b0aedb77f15be6a5d1451c915c0c20b2fe6\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OracleUtils.sol\\\";\\n\\n// @title IOracleProvider\\n// @dev Interface for an oracle provider\\ninterface IOracleProvider {\\n function getOraclePrice(\\n address token,\\n bytes memory data\\n ) external returns (OracleUtils.ValidatedPrice memory);\\n\\n /// @dev for all oracle providers besides ChainlinkPriceFeedProvider\\n function shouldAdjustTimestamp() external pure returns (bool);\\n\\n /// @dev for ChainlinkPriceFeedProvider\\n function isChainlinkOnChainProvider() external pure returns (bool);\\n}\\n\",\"keccak256\":\"0x8d58f6373f8894c71e559e845db06043047c4ccdf9fac827f8cdf41044b3b1f6\",\"license\":\"MIT\"},\"contracts/oracle/IPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n// @title IPriceFeed\\n// @dev Interface for a price feed\\ninterface IPriceFeed {\\n function latestRoundData() external view returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function description() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x5474d86a80fde875ffd0b52d2806554b32bf10c33553ecae7de1f82400bcf5b6\",\"license\":\"MIT\"},\"contracts/oracle/Oracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport { AggregatorV2V3Interface } from \\\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\\\";\\n\\nimport \\\"../role/RoleModule.sol\\\";\\n\\nimport \\\"./OracleUtils.sol\\\";\\nimport \\\"./IOracle.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\nimport \\\"./ChainlinkPriceFeedUtils.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\nimport \\\"../utils/Uint256Mask.sol\\\";\\n\\n// @title Oracle\\n// @dev Contract to validate and store signed values\\n// Some calculations e.g. calculating the size in tokens for a position\\n// may not work with zero / negative prices\\n// as a result, zero / negative prices are considered empty / invalid\\n// A market may need to be manually settled in this case\\ncontract Oracle is IOracle, RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using Price for Price.Props;\\n using Uint256Mask for Uint256Mask.Mask;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n AggregatorV2V3Interface public immutable sequencerUptimeFeed;\\n\\n // tokensWithPrices stores the tokens with prices that have been set\\n // this is used in clearAllPrices to help ensure that all token prices\\n // set in setPrices are cleared after use\\n EnumerableSet.AddressSet internal tokensWithPrices;\\n mapping(address => Price.Props) public primaryPrices;\\n\\n uint256 public minTimestamp;\\n uint256 public maxTimestamp;\\n\\n constructor(\\n RoleStore _roleStore,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter,\\n AggregatorV2V3Interface _sequencerUptimeFeed\\n ) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n sequencerUptimeFeed = _sequencerUptimeFeed;\\n }\\n\\n // this can be used to help ensure that on-chain prices are updated\\n // before actions dependent on those on-chain prices are allowed\\n // additionally, this can also be used to provide a grace period for\\n // users to top up collateral before liquidations occur\\n function validateSequencerUp() public view {\\n if (address(sequencerUptimeFeed) == address(0)) {\\n return;\\n }\\n\\n (\\n /*uint80 roundID*/,\\n int256 answer,\\n uint256 startedAt,\\n /*uint256 updatedAt*/,\\n /*uint80 answeredInRound*/\\n ) = sequencerUptimeFeed.latestRoundData();\\n\\n // answer == 0: sequencer is up\\n // answer == 1: sequencer is down\\n bool isSequencerUp = answer == 0;\\n if (!isSequencerUp) {\\n revert Errors.SequencerDown();\\n }\\n\\n uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);\\n\\n // ensure the grace duration has passed after the\\n // sequencer is back up.\\n uint256 timeSinceUp = block.timestamp - startedAt;\\n if (timeSinceUp <= sequencerGraceDuration) {\\n revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);\\n }\\n }\\n\\n function setPrices(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);\\n\\n _setPrices(prices);\\n }\\n\\n function setPricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n validateSequencerUp();\\n\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);\\n\\n _setPrices(prices);\\n }\\n\\n // @dev set the primary price\\n // @param token the token to set the price for\\n // @param price the price value to set to\\n function setPrimaryPrice(address token, Price.Props memory price) external onlyController {\\n _setPrimaryPrice(token, price);\\n }\\n\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n // @dev clear all prices\\n function clearAllPrices() external onlyController {\\n uint256 length = tokensWithPrices.length();\\n for (uint256 i; i < length; i++) {\\n address token = tokensWithPrices.at(0);\\n _removePrimaryPrice(token);\\n }\\n\\n minTimestamp = 0;\\n maxTimestamp = 0;\\n }\\n\\n // @dev get the length of tokensWithPrices\\n // @return the length of tokensWithPrices\\n function getTokensWithPricesCount() external view returns (uint256) {\\n return tokensWithPrices.length();\\n }\\n\\n // @dev get the tokens of tokensWithPrices for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the tokens of tokensWithPrices for the specified indexes\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {\\n return tokensWithPrices.valuesAt(start, end);\\n }\\n\\n // @dev get the primary price of a token\\n // @param token the token to get the price for\\n // @return the primary price of a token\\n function getPrimaryPrice(address token) external view returns (Price.Props memory) {\\n if (token == address(0)) { return Price.Props(0, 0); }\\n\\n Price.Props memory price = primaryPrices[token];\\n if (price.isEmpty()) {\\n revert Errors.EmptyPrimaryPrice(token);\\n }\\n\\n return price;\\n }\\n\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {\\n return _validatePrices(params, forAtomicAction);\\n }\\n\\n // @dev validate and set prices\\n // @param params OracleUtils.SetPricesParams\\n function _setPrices(\\n OracleUtils.ValidatedPrice[] memory prices\\n ) internal {\\n // in case of gasless relay the prices are not required if there is no need to swap fee tokens\\n if (prices.length == 0) {\\n return;\\n }\\n\\n if (tokensWithPrices.length() != 0) {\\n revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());\\n }\\n\\n uint256 _minTimestamp = prices[0].timestamp;\\n uint256 _maxTimestamp = prices[0].timestamp;\\n\\n for (uint256 i; i < prices.length; i++) {\\n OracleUtils.ValidatedPrice memory validatedPrice = prices[i];\\n\\n _setPrimaryPrice(validatedPrice.token, Price.Props(\\n validatedPrice.min,\\n validatedPrice.max\\n ));\\n\\n if (validatedPrice.timestamp < _minTimestamp) {\\n _minTimestamp = validatedPrice.timestamp;\\n }\\n\\n if (validatedPrice.timestamp > _maxTimestamp) {\\n _maxTimestamp = validatedPrice.timestamp;\\n }\\n\\n _emitOraclePriceUpdated(\\n validatedPrice.token,\\n validatedPrice.min,\\n validatedPrice.max,\\n validatedPrice.timestamp,\\n validatedPrice.provider\\n );\\n }\\n\\n uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);\\n if (_maxTimestamp - _minTimestamp > maxRange) {\\n revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);\\n }\\n\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n function _validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) internal returns (OracleUtils.ValidatedPrice[] memory) {\\n if (params.tokens.length != params.providers.length) {\\n revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);\\n }\\n\\n if (params.tokens.length != params.data.length) {\\n revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);\\n }\\n\\n OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);\\n\\n if (params.tokens.length == 0) {\\n return prices;\\n }\\n\\n uint256 maxPriceAge = forAtomicAction ? dataStore.getUint(Keys.MAX_ATOMIC_ORACLE_PRICE_AGE) : dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);\\n uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);\\n\\n for (uint256 i; i < params.tokens.length; i++) {\\n address _provider = params.providers[i];\\n IOracleProvider provider = IOracleProvider(_provider);\\n\\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(_provider))) {\\n revert Errors.InvalidOracleProvider(_provider);\\n }\\n\\n address token = params.tokens[i];\\n\\n bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(_provider));\\n\\n // if the action is atomic then only validate that the provider is an\\n // atomic provider\\n // else, validate that the provider matches the oracleProviderForToken\\n //\\n // since for atomic actions, any atomic provider can be used, it is\\n // recommended that only one atomic provider is configured per token\\n // otherwise there is a risk that if there is a difference in pricing\\n // between atomic oracle providers for a token, a user could use that\\n // to gain a profit by alternating actions between the two atomic\\n // providers\\n if (forAtomicAction) {\\n if (!isAtomicProvider) {\\n revert Errors.NonAtomicOracleProvider(_provider);\\n }\\n } else {\\n address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(address(this), token));\\n if (_provider != expectedProvider) {\\n revert Errors.InvalidOracleProviderForToken(_provider, expectedProvider);\\n }\\n }\\n\\n bytes memory data = params.data[i];\\n\\n OracleUtils.ValidatedPrice memory validatedPrice = provider.getOraclePrice(\\n token,\\n data\\n );\\n\\n // for atomic providers, the timestamp will be the current block's timestamp\\n // the timestamp should not be adjusted\\n if (provider.shouldAdjustTimestamp()) {\\n uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(_provider, token));\\n validatedPrice.timestamp -= timestampAdjustment;\\n }\\n\\n if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {\\n revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());\\n }\\n\\n if (!provider.isChainlinkOnChainProvider()) {\\n (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\\n\\n if (hasRefPrice) {\\n _validateRefPrice(\\n token,\\n validatedPrice.min,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n\\n _validateRefPrice(\\n token,\\n validatedPrice.max,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n prices[i] = validatedPrice;\\n }\\n\\n return prices;\\n }\\n\\n function _validateRefPrice(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n ) internal pure {\\n uint256 diff = Calc.diff(price, refPrice);\\n uint256 diffFactor = Precision.toFactor(diff, refPrice);\\n\\n if (diffFactor > maxRefPriceDeviationFactor) {\\n revert Errors.MaxRefPriceDeviationExceeded(\\n token,\\n price,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n function _setPrimaryPrice(address token, Price.Props memory price) internal {\\n if (price.min > price.max) {\\n revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);\\n }\\n\\n Price.Props memory existingPrice = primaryPrices[token];\\n\\n if (!existingPrice.isEmpty()) {\\n revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);\\n }\\n\\n primaryPrices[token] = price;\\n tokensWithPrices.add(token);\\n }\\n\\n function _removePrimaryPrice(address token) internal {\\n delete primaryPrices[token];\\n tokensWithPrices.remove(token);\\n }\\n\\n function _emitOraclePriceUpdated(\\n address token,\\n uint256 minPrice,\\n uint256 maxPrice,\\n uint256 timestamp,\\n address provider\\n ) internal {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"provider\\\", provider);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"minPrice\\\", minPrice);\\n eventData.uintItems.setItem(1, \\\"maxPrice\\\", maxPrice);\\n eventData.uintItems.setItem(2, \\\"timestamp\\\", timestamp);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OraclePriceUpdate\\\",\\n Cast.toBytes32(token),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x37cac3c6590c434acbf8b391b6a6fb875ecb671e2859f473d17d5afe7e1e38e5\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IOracle.sol\\\";\\n\\n// @title OracleModule\\n// @dev Provides convenience functions for interacting with the Oracle\\ncontract OracleModule {\\n IOracle public immutable oracle;\\n\\n constructor(IOracle _oracle) {\\n oracle = _oracle;\\n }\\n\\n // @dev sets oracle prices, perform any additional tasks required,\\n // and clear the oracle prices after\\n //\\n // care should be taken to avoid re-entrancy while using this call\\n // since re-entrancy could allow functions to be called with prices\\n // meant for a different type of transaction\\n // the tokensWithPrices.length check in oracle.setPrices should help\\n // mitigate this\\n //\\n // @param params OracleUtils.SetPricesParams\\n modifier withOraclePrices(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPrices(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n modifier withOraclePricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPricesForAtomicAction(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n // @dev set oracle prices for a simulation\\n // tokensWithPrices is not set in this function\\n // it is possible for withSimulatedOraclePrices to be called and a function\\n // using withOraclePrices to be called after\\n // or for a function using withOraclePrices to be called and withSimulatedOraclePrices\\n // called after\\n // this should not cause an issue because this transaction should always revert\\n // and any state changes based on simulated prices as well as the setting of simulated\\n // prices should not be persisted\\n // @param params OracleUtils.SimulatePricesParams\\n modifier withSimulatedOraclePrices(\\n OracleUtils.SimulatePricesParams memory params\\n ) {\\n if (params.primaryTokens.length != params.primaryPrices.length) {\\n revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);\\n }\\n\\n for (uint256 i; i < params.primaryTokens.length; i++) {\\n address token = params.primaryTokens[i];\\n Price.Props memory price = params.primaryPrices[i];\\n oracle.setPrimaryPrice(token, price);\\n }\\n\\n oracle.setTimestamps(params.minTimestamp, params.maxTimestamp);\\n\\n _;\\n\\n revert Errors.EndOfOracleSimulation();\\n }\\n}\\n\",\"keccak256\":\"0x19e4098e3f037bb6e1deb3a93aa98d42ceac46bf10553fb9aff784f9fbbc16ff\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\n// @title OracleStore\\n// @dev Stores the list of oracle signers\\ncontract OracleStore is RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n EventEmitter public immutable eventEmitter;\\n\\n EnumerableSet.AddressSet internal signers;\\n\\n constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {\\n eventEmitter = _eventEmitter;\\n }\\n\\n // @dev adds a signer\\n // @param account address of the signer to add\\n function addSigner(address account) external onlyController {\\n signers.add(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerAdded\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev removes a signer\\n // @param account address of the signer to remove\\n function removeSigner(address account) external onlyController {\\n signers.remove(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerRemoved\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev get the total number of signers\\n // @return the total number of signers\\n function getSignerCount() external view returns (uint256) {\\n return signers.length();\\n }\\n\\n // @dev get the signer at the specified index\\n // @param index the index of the signer to get\\n // @return the signer at the specified index\\n function getSigner(uint256 index) external view returns (address) {\\n return signers.at(index);\\n }\\n\\n // @dev get the signers for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the signers for the specified indexes\\n function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {\\n return signers.valuesAt(start, end);\\n }\\n}\\n\",\"keccak256\":\"0x5b9c2917e29aa696a8385f9f8b6a0cd0f1ef9a0b08d8096a2f19367e89cc09e7\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0xa7a5a10c9321e7372bc6a8c11da319e6421ed5c0676810a1c8ec30c30f730331\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Uint256Mask.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary Uint256Mask {\\n struct Mask {\\n uint256 bits;\\n }\\n\\n function validateUniqueAndSetIndex(\\n Mask memory mask,\\n uint256 index,\\n string memory label\\n ) internal pure {\\n if (index >= 256) {\\n revert Errors.MaskIndexOutOfBounds(index, label);\\n }\\n\\n uint256 bit = 1 << index;\\n\\n if (mask.bits & bit != 0) {\\n revert Errors.DuplicatedIndex(index, label);\\n }\\n\\n mask.bits = mask.bits | bit;\\n }\\n}\\n\",\"keccak256\":\"0x96aaf43efa3a092b2d8d1e88addab6c31f5a7f526b84a290b9ba43e803592e01\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x60e060405234801561001057600080fd5b50604051612b15380380612b1583398101604081905261002f916103e6565b828686863361004c600080516020612a958339815191528061020b565b610072600080516020612ab5833981519152600080516020612a9583398151915261020b565b610098600080516020612ad5833981519152600080516020612a9583398151915261020b565b6100be600080516020612af5833981519152600080516020612a9583398151915261020b565b6100d6600080516020612a9583398151915230610256565b6001600160a01b038116156100fd576100fd600080516020612a9583398151915282610256565b60005b835181101561016c57610140600080516020612ab583398151915285838151811061012d5761012d610494565b602002602001015161025660201b60201c565b610164600080516020612af583398151915285838151811061012d5761012d610494565b600101610100565b5060005b82518110156101a55761019d600080516020612ad583398151915284838151811061012d5761012d610494565b600101610170565b5060028490556040805160008152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a15050506001600160a01b039182166080525091821660a0521660c052506104aa92505050565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6102608282610264565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610260576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556102be3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461032d57600080fd5b50565b805161033b81610318565b919050565b600082601f83011261035157600080fd5b81516001600160401b0381111561036a5761036a610302565b604051600582901b90603f8201601f191681016001600160401b038111828210171561039857610398610302565b6040529182526020818501810192908101868411156103b657600080fd5b6020860192505b838310156103dc576103ce83610330565b8152602092830192016103bd565b5095945050505050565b60008060008060008060c087890312156103ff57600080fd5b865160208801519096506001600160401b0381111561041d57600080fd5b61042989828a01610340565b604089015190965090506001600160401b0381111561044757600080fd5b61045389828a01610340565b945050606087015161046481610318565b608088015190935061047581610318565b60a088015190925061048681610318565b809150509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c051612584610511600039600081816104df0152818161094c01526110820152600081816103dd0152818161092a01526110600152600081816104290152818161096e01528181610d8f01528181610e0601526110a401526125846000f3fe60806040526004361061018d5760003560e01c806301d5062a1461019957806301ffc9a7146101bb57806307bd0265146101f05780630d3cf6fc14610220578063134008d31461025457806313bc9f2014610267578063150b7a0214610287578063248a9ca3146102cb5780632ab0f529146102eb5780632f2ff15d1461030b57806331d507501461032b57806336568abe1461034b578063575d346a1461036b578063584b153e1461038b57806364d62353146103ab578063660d0d67146103cb5780637dc0d1d0146104175780638065657f1461044b5780638f2a0bb01461046b5780638f61f4f51461048b57806391d14854146104ad5780639ff78c30146104cd578063a217fddf14610501578063b08e51c014610516578063b1c5f42714610538578063bc197c8114610558578063c4d252f514610584578063d0663e61146105a4578063d45c4435146105c4578063d547741f146105e4578063e38335e514610604578063f128024b14610617578063f23a6e6114610637578063f27a0c921461066357600080fd5b3661019457005b600080fd5b3480156101a557600080fd5b506101b96101b43660046116f3565b610678565b005b3480156101c757600080fd5b506101db6101d6366004611767565b610718565b60405190151581526020015b60405180910390f35b3480156101fc57600080fd5b506102126000805160206124cf83398151915281565b6040519081526020016101e7565b34801561022c57600080fd5b506102127f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101b9610262366004611791565b610743565b34801561027357600080fd5b506101db6102823660046117fc565b6107d4565b34801561029357600080fd5b506102b26102a23660046118f2565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016101e7565b3480156102d757600080fd5b506102126102e63660046117fc565b6107f9565b3480156102f757600080fd5b506101db6103063660046117fc565b61080e565b34801561031757600080fd5b506101b9610326366004611959565b610822565b34801561033757600080fd5b506101db6103463660046117fc565b610843565b34801561035757600080fd5b506101b9610366366004611959565b610856565b34801561037757600080fd5b506101b9610386366004611985565b6108d9565b34801561039757600080fd5b506101db6103a63660046117fc565b6109d1565b3480156103b757600080fd5b506101b96103c63660046117fc565b6109de565b3480156103d757600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e7565b34801561042357600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045757600080fd5b50610212610466366004611791565b610a82565b34801561047757600080fd5b506101b9610486366004611a06565b610ac1565b34801561049757600080fd5b506102126000805160206124af83398151915281565b3480156104b957600080fd5b506101db6104c8366004611959565b610c16565b3480156104d957600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561050d57600080fd5b50610212600081565b34801561052257600080fd5b5061021260008051602061250f83398151915281565b34801561054457600080fd5b50610212610553366004611ac1565b610c3f565b34801561056457600080fd5b506102b2610573366004611c03565b63bc197c8160e01b95945050505050565b34801561059057600080fd5b506101b961059f3660046117fc565b610c84565b3480156105b057600080fd5b506101b96105bf366004611cb6565b610d47565b3480156105d057600080fd5b506102126105df3660046117fc565b610e81565b3480156105f057600080fd5b506101b96105ff366004611959565b610e93565b6101b9610612366004611ac1565b610eaf565b34801561062357600080fd5b506101b9610632366004611985565b61100f565b34801561064357600080fd5b506102b2610652366004611d57565b63f23a6e6160e01b95945050505050565b34801561066f57600080fd5b50600254610212565b6000805160206124af833981519152610690816110d2565b60006106a0898989898989610a82565b90506106ac81846110df565b6000816000805160206124ef8339815191528b8b8b8b8b8a6040516106d696959493929190611dd8565b60405180910390a3831561070d578060008051602061252f8339815191528560405161070491815260200190565b60405180910390a25b505050505050505050565b60006001600160e01b03198216630271189760e51b148061073d575061073d826111ce565b92915050565b6000805160206124cf83398151915261075d816000610c16565b61076b5761076b8133611203565b600061077b888888888888610a82565b9050610787818561125c565b610793888888886112ed565b60008160008051602061248f8339815191528a8a8a8a6040516107b99493929190611e15565b60405180910390a36107ca816113c0565b5050505050505050565b6000806107e083610e81565b90506001811180156107f25750428111155b9392505050565b60009081526020819052604090206001015490565b6000600161081b83610e81565b1492915050565b61082b826107f9565b610834816110d2565b61083e83836113f9565b505050565b60008061084f83610e81565b1192915050565b6001600160a01b03811633146108cb5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108d5828261147d565b5050565b3330146108fb573360405163a35b150b60e01b81526004016108c29190611e47565b604051630520f17f60e21b81527388a5c6D94634Abd7745f5348e5D8C42868ed4AC390631483c5fc9061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b60006040518083038186803b1580156109b457600080fd5b505af41580156109c8573d6000803e3d6000fd5b50505050505050565b6000600161084f83610e81565b333014610a415760405162461bcd60e51b815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201526a62652074696d656c6f636b60a81b60648201526084016108c2565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610a9f96959493929190611dd8565b6040516020818303038152906040528051906020012090509695505050505050565b6000805160206124af833981519152610ad9816110d2565b888714610af85760405162461bcd60e51b81526004016108c290611eb2565b888514610b175760405162461bcd60e51b81526004016108c290611eb2565b6000610b298b8b8b8b8b8b8b8b610c3f565b9050610b3581846110df565b60005b8a811015610bd95780826000805160206124ef8339815191528e8e85818110610b6357610b63611ef5565b9050602002016020810190610b789190611f0b565b8d8d86818110610b8a57610b8a611ef5565b905060200201358c8c87818110610ba357610ba3611ef5565b9050602002810190610bb59190611f26565b8c8b604051610bc996959493929190611dd8565b60405180910390a3600101610b38565b508315610c09578060008051602061252f83398151915285604051610c0091815260200190565b60405180910390a25b5050505050505050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008888888888888888604051602001610c60989796959493929190612005565b60405160208183030381529060405280519060200120905098975050505050505050565b60008051602061250f833981519152610c9c816110d2565b610ca5826109d1565b610d0b5760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e2063616044820152701b9b9bdd0818994818d85b98d95b1b1959607a1b60648201526084016108c2565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b6000805160206124cf833981519152610d61816000610c16565b610d6f57610d6f8133611203565b610d788261210b565b6040516331e999fd60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c7a667f490610dc49084906004016122b5565b600060405180830381600087803b158015610dde57600080fd5b505af1158015610df2573d6000803e3d6000fd5b50505050610e04898989898989610743565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662ccf1556040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e5e57600080fd5b505af1158015610e72573d6000803e3d6000fd5b50505050505050505050505050565b60009081526001602052604090205490565b610e9c826107f9565b610ea5816110d2565b61083e838361147d565b6000805160206124cf833981519152610ec9816000610c16565b610ed757610ed78133611203565b878614610ef65760405162461bcd60e51b81526004016108c290611eb2565b878414610f155760405162461bcd60e51b81526004016108c290611eb2565b6000610f278a8a8a8a8a8a8a8a610c3f565b9050610f33818561125c565b60005b89811015610ff95760008b8b83818110610f5257610f52611ef5565b9050602002016020810190610f679190611f0b565b905060008a8a84818110610f7d57610f7d611ef5565b9050602002013590503660008a8a86818110610f9b57610f9b611ef5565b9050602002810190610fad9190611f26565b91509150610fbd848484846112ed565b848660008051602061248f83398151915286868686604051610fe29493929190611e15565b60405180910390a350505050806001019050610f36565b50611003816113c0565b50505050505050505050565b333014611031573360405163a35b150b60e01b81526004016108c29190611e47565b604051639166d48160e01b81527388a5c6D94634Abd7745f5348e5D8C42868ed4AC390639166d4819061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b6110dc8133611203565b50565b6110e882610843565b1561114d5760405162461bcd60e51b815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201526e1c9958591e481cd8da19591d5b1959608a1b60648201526084016108c2565b6002548110156111ae5760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e746044820152652064656c617960d01b60648201526084016108c2565b6111b88142612371565b6000928352600160205260409092209190915550565b60006001600160e01b03198216637965db0b60e01b148061073d57506301ffc9a760e01b6001600160e01b031983161461073d565b61120d8282610c16565b6108d55761121a816114e2565b6112258360206114f4565b604051602001611236929190612384565b60408051601f198184030181529082905262461bcd60e51b82526108c2916004016123f3565b611265826107d4565b6112815760405162461bcd60e51b81526004016108c290612406565b80158061129257506112928161080e565b6108d55760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e6720646570656044820152656e64656e637960d01b60648201526084016108c2565b6000846001600160a01b031684848460405161130a929190612450565b60006040518083038185875af1925050503d8060008114611347576040519150601f19603f3d011682016040523d82523d6000602084013e61134c565b606091505b50509050806113b95760405162461bcd60e51b815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e6720746044820152721c985b9cd858dd1a5bdb881c995d995c9d1959606a1b60648201526084016108c2565b5050505050565b6113c9816107d4565b6113e55760405162461bcd60e51b81526004016108c290612406565b600090815260016020819052604090912055565b6114038282610c16565b6108d5576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556114393390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114878282610c16565b156108d5576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b606061073d6001600160a01b03831660145b60606000611503836002612460565b61150e906002612371565b6001600160401b0381111561152557611525611815565b6040519080825280601f01601f19166020018201604052801561154f576020820181803683370190505b509050600360fc1b8160008151811061156a5761156a611ef5565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061159957611599611ef5565b60200101906001600160f81b031916908160001a90535060006115bd846002612460565b6115c8906001612371565b90505b6001811115611640576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106115fc576115fc611ef5565b1a60f81b82828151811061161257611612611ef5565b60200101906001600160f81b031916908160001a90535060049490941c9361163981612477565b90506115cb565b5083156107f25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108c2565b80356001600160a01b03811681146116a657600080fd5b919050565b60008083601f8401126116bd57600080fd5b5081356001600160401b038111156116d457600080fd5b6020830191508360208285010111156116ec57600080fd5b9250929050565b600080600080600080600060c0888a03121561170e57600080fd5b6117178861168f565b96506020880135955060408801356001600160401b0381111561173957600080fd5b6117458a828b016116ab565b989b979a50986060810135976080820135975060a09091013595509350505050565b60006020828403121561177957600080fd5b81356001600160e01b0319811681146107f257600080fd5b60008060008060008060a087890312156117aa57600080fd5b6117b38761168f565b95506020870135945060408701356001600160401b038111156117d557600080fd5b6117e189828a016116ab565b979a9699509760608101359660809091013595509350505050565b60006020828403121561180e57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561184d5761184d611815565b60405290565b604051601f8201601f191681016001600160401b038111828210171561187b5761187b611815565b604052919050565b600082601f83011261189457600080fd5b81356001600160401b038111156118ad576118ad611815565b6118c0601f8201601f1916602001611853565b8181528460208386010111156118d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561190857600080fd5b6119118561168f565b935061191f6020860161168f565b92506040850135915060608501356001600160401b0381111561194157600080fd5b61194d87828801611883565b91505092959194509250565b6000806040838503121561196c57600080fd5b8235915061197c6020840161168f565b90509250929050565b60008060006060848603121561199a57600080fd5b6119a38461168f565b92506119b16020850161168f565b929592945050506040919091013590565b60008083601f8401126119d457600080fd5b5081356001600160401b038111156119eb57600080fd5b6020830191508360208260051b85010111156116ec57600080fd5b600080600080600080600080600060c08a8c031215611a2457600080fd5b89356001600160401b03811115611a3a57600080fd5b611a468c828d016119c2565b909a5098505060208a01356001600160401b03811115611a6557600080fd5b611a718c828d016119c2565b90985096505060408a01356001600160401b03811115611a9057600080fd5b611a9c8c828d016119c2565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b031215611add57600080fd5b88356001600160401b03811115611af357600080fd5b611aff8b828c016119c2565b90995097505060208901356001600160401b03811115611b1e57600080fd5b611b2a8b828c016119c2565b90975095505060408901356001600160401b03811115611b4957600080fd5b611b558b828c016119c2565b999c989b509699959896976060870135966080013595509350505050565b60006001600160401b03821115611b8c57611b8c611815565b5060051b60200190565b600082601f830112611ba757600080fd5b8135611bba611bb582611b73565b611853565b8082825260208201915060208360051b860101925085831115611bdc57600080fd5b602085015b83811015611bf9578035835260209283019201611be1565b5095945050505050565b600080600080600060a08688031215611c1b57600080fd5b611c248661168f565b9450611c326020870161168f565b935060408601356001600160401b03811115611c4d57600080fd5b611c5988828901611b96565b93505060608601356001600160401b03811115611c7557600080fd5b611c8188828901611b96565b92505060808601356001600160401b03811115611c9d57600080fd5b611ca988828901611883565b9150509295509295909350565b600080600080600080600060c0888a031215611cd157600080fd5b611cda8861168f565b96506020880135955060408801356001600160401b03811115611cfc57600080fd5b611d088a828b016116ab565b909650945050606088013592506080880135915060a08801356001600160401b03811115611d3557600080fd5b88016060818b031215611d4757600080fd5b8091505092959891949750929550565b600080600080600060a08688031215611d6f57600080fd5b611d788661168f565b9450611d866020870161168f565b9350604086013592506060860135915060808601356001600160401b03811115611c9d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201526000611e0060a083018688611daf565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201526000611e3d606083018486611daf565b9695505050505050565b6001600160a01b039190911681526040602082018190526004908201526329a2a62360e11b606082015260800190565b6001600160a01b039687168152948616602086015292851660408501529084166060840152909216608082015260a081019190915260c00190565b60208082526023908201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d616040820152620e8c6d60eb1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611f1d57600080fd5b6107f28261168f565b6000808335601e19843603018112611f3d57600080fd5b8301803591506001600160401b03821115611f5757600080fd5b6020019150368190038213156116ec57600080fd5b60008383855260208501945060208460051b8201018360005b86811015611ff957838303601f19018852813536879003601e19018112611fab57600080fd5b86016020810190356001600160401b03811115611fc757600080fd5b803603821315611fd657600080fd5b611fe1858284611daf565b60209a8b019a90955093909301925050600101611f85565b50909695505050505050565b60a0808252810188905260008960c08301825b8b811015612046576001600160a01b036120318461168f565b16825260209283019290910190600101612018565b5083810360208501528881526001600160fb1b0389111561206657600080fd5b8860051b9150818a6020830137018281036020908101604085015261208e9082018789611f6c565b60608401959095525050608001529695505050505050565b600082601f8301126120b757600080fd5b81356120c5611bb582611b73565b8082825260208201915060208360051b8601019250858311156120e757600080fd5b602085015b83811015611bf9576120fd8161168f565b8352602092830192016120ec565b60006060823603121561211d57600080fd5b61212561182b565b82356001600160401b0381111561213b57600080fd5b612147368286016120a6565b82525060208301356001600160401b0381111561216357600080fd5b61216f368286016120a6565b60208301525060408301356001600160401b0381111561218e57600080fd5b830136601f82011261219f57600080fd5b80356121ad611bb582611b73565b8082825260208201915060208360051b8501019250368311156121cf57600080fd5b602084015b838110156122105780356001600160401b038111156121f257600080fd5b61220136602083890101611883565b845250602092830192016121d4565b5060408501525091949350505050565b600081518084526020840193506020830160005b8281101561225b5781516001600160a01b0316865260209586019590910190600101612234565b5093949350505050565b60005b83811015612280578181015183820152602001612268565b50506000910152565b600081518084526122a1816020860160208601612265565b601f01601f19169290920160200192915050565b6020815260008251606060208401526122d16080840182612220565b90506020840151601f198483030160408501526122ee8282612220565b6040860151858203601f190160608701528051808352919350602090810192508084019190600582901b85010160005b8281101561234f57601f1986830301845261233a828651612289565b6020958601959490940193915060010161231e565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561073d5761073d61235b565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516123b6816017850160208801612265565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516123e7816028840160208801612265565b01602801949350505050565b6020815260006107f26020830184612289565b6020808252602a908201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e206973604082015269206e6f7420726561647960b01b606082015260800190565b8183823760009101908152919050565b808202811582820484141761073d5761073d61235b565b6000816124865761248661235b565b50600019019056fec2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e634cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dcafd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78320fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387a2646970667358221220e300d21dcc10a518d439862cbd95c0bbfaa061197c2ee778427b4626af874f8164736f6c634300081d00335f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63fd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", + "deployedBytecode": "0x60806040526004361061018d5760003560e01c806301d5062a1461019957806301ffc9a7146101bb57806307bd0265146101f05780630d3cf6fc14610220578063134008d31461025457806313bc9f2014610267578063150b7a0214610287578063248a9ca3146102cb5780632ab0f529146102eb5780632f2ff15d1461030b57806331d507501461032b57806336568abe1461034b578063575d346a1461036b578063584b153e1461038b57806364d62353146103ab578063660d0d67146103cb5780637dc0d1d0146104175780638065657f1461044b5780638f2a0bb01461046b5780638f61f4f51461048b57806391d14854146104ad5780639ff78c30146104cd578063a217fddf14610501578063b08e51c014610516578063b1c5f42714610538578063bc197c8114610558578063c4d252f514610584578063d0663e61146105a4578063d45c4435146105c4578063d547741f146105e4578063e38335e514610604578063f128024b14610617578063f23a6e6114610637578063f27a0c921461066357600080fd5b3661019457005b600080fd5b3480156101a557600080fd5b506101b96101b43660046116f3565b610678565b005b3480156101c757600080fd5b506101db6101d6366004611767565b610718565b60405190151581526020015b60405180910390f35b3480156101fc57600080fd5b506102126000805160206124cf83398151915281565b6040519081526020016101e7565b34801561022c57600080fd5b506102127f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101b9610262366004611791565b610743565b34801561027357600080fd5b506101db6102823660046117fc565b6107d4565b34801561029357600080fd5b506102b26102a23660046118f2565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016101e7565b3480156102d757600080fd5b506102126102e63660046117fc565b6107f9565b3480156102f757600080fd5b506101db6103063660046117fc565b61080e565b34801561031757600080fd5b506101b9610326366004611959565b610822565b34801561033757600080fd5b506101db6103463660046117fc565b610843565b34801561035757600080fd5b506101b9610366366004611959565b610856565b34801561037757600080fd5b506101b9610386366004611985565b6108d9565b34801561039757600080fd5b506101db6103a63660046117fc565b6109d1565b3480156103b757600080fd5b506101b96103c63660046117fc565b6109de565b3480156103d757600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e7565b34801561042357600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561045757600080fd5b50610212610466366004611791565b610a82565b34801561047757600080fd5b506101b9610486366004611a06565b610ac1565b34801561049757600080fd5b506102126000805160206124af83398151915281565b3480156104b957600080fd5b506101db6104c8366004611959565b610c16565b3480156104d957600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b34801561050d57600080fd5b50610212600081565b34801561052257600080fd5b5061021260008051602061250f83398151915281565b34801561054457600080fd5b50610212610553366004611ac1565b610c3f565b34801561056457600080fd5b506102b2610573366004611c03565b63bc197c8160e01b95945050505050565b34801561059057600080fd5b506101b961059f3660046117fc565b610c84565b3480156105b057600080fd5b506101b96105bf366004611cb6565b610d47565b3480156105d057600080fd5b506102126105df3660046117fc565b610e81565b3480156105f057600080fd5b506101b96105ff366004611959565b610e93565b6101b9610612366004611ac1565b610eaf565b34801561062357600080fd5b506101b9610632366004611985565b61100f565b34801561064357600080fd5b506102b2610652366004611d57565b63f23a6e6160e01b95945050505050565b34801561066f57600080fd5b50600254610212565b6000805160206124af833981519152610690816110d2565b60006106a0898989898989610a82565b90506106ac81846110df565b6000816000805160206124ef8339815191528b8b8b8b8b8a6040516106d696959493929190611dd8565b60405180910390a3831561070d578060008051602061252f8339815191528560405161070491815260200190565b60405180910390a25b505050505050505050565b60006001600160e01b03198216630271189760e51b148061073d575061073d826111ce565b92915050565b6000805160206124cf83398151915261075d816000610c16565b61076b5761076b8133611203565b600061077b888888888888610a82565b9050610787818561125c565b610793888888886112ed565b60008160008051602061248f8339815191528a8a8a8a6040516107b99493929190611e15565b60405180910390a36107ca816113c0565b5050505050505050565b6000806107e083610e81565b90506001811180156107f25750428111155b9392505050565b60009081526020819052604090206001015490565b6000600161081b83610e81565b1492915050565b61082b826107f9565b610834816110d2565b61083e83836113f9565b505050565b60008061084f83610e81565b1192915050565b6001600160a01b03811633146108cb5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108d5828261147d565b5050565b3330146108fb573360405163a35b150b60e01b81526004016108c29190611e47565b604051630520f17f60e21b815273__$7cc2376e36274fcb28d593438dccae7b38$__90631483c5fc9061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b60006040518083038186803b1580156109b457600080fd5b505af41580156109c8573d6000803e3d6000fd5b50505050505050565b6000600161084f83610e81565b333014610a415760405162461bcd60e51b815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201526a62652074696d656c6f636b60a81b60648201526084016108c2565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610a9f96959493929190611dd8565b6040516020818303038152906040528051906020012090509695505050505050565b6000805160206124af833981519152610ad9816110d2565b888714610af85760405162461bcd60e51b81526004016108c290611eb2565b888514610b175760405162461bcd60e51b81526004016108c290611eb2565b6000610b298b8b8b8b8b8b8b8b610c3f565b9050610b3581846110df565b60005b8a811015610bd95780826000805160206124ef8339815191528e8e85818110610b6357610b63611ef5565b9050602002016020810190610b789190611f0b565b8d8d86818110610b8a57610b8a611ef5565b905060200201358c8c87818110610ba357610ba3611ef5565b9050602002810190610bb59190611f26565b8c8b604051610bc996959493929190611dd8565b60405180910390a3600101610b38565b508315610c09578060008051602061252f83398151915285604051610c0091815260200190565b60405180910390a25b5050505050505050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008888888888888888604051602001610c60989796959493929190612005565b60405160208183030381529060405280519060200120905098975050505050505050565b60008051602061250f833981519152610c9c816110d2565b610ca5826109d1565b610d0b5760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e2063616044820152701b9b9bdd0818994818d85b98d95b1b1959607a1b60648201526084016108c2565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b6000805160206124cf833981519152610d61816000610c16565b610d6f57610d6f8133611203565b610d788261210b565b6040516331e999fd60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c7a667f490610dc49084906004016122b5565b600060405180830381600087803b158015610dde57600080fd5b505af1158015610df2573d6000803e3d6000fd5b50505050610e04898989898989610743565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662ccf1556040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e5e57600080fd5b505af1158015610e72573d6000803e3d6000fd5b50505050505050505050505050565b60009081526001602052604090205490565b610e9c826107f9565b610ea5816110d2565b61083e838361147d565b6000805160206124cf833981519152610ec9816000610c16565b610ed757610ed78133611203565b878614610ef65760405162461bcd60e51b81526004016108c290611eb2565b878414610f155760405162461bcd60e51b81526004016108c290611eb2565b6000610f278a8a8a8a8a8a8a8a610c3f565b9050610f33818561125c565b60005b89811015610ff95760008b8b83818110610f5257610f52611ef5565b9050602002016020810190610f679190611f0b565b905060008a8a84818110610f7d57610f7d611ef5565b9050602002013590503660008a8a86818110610f9b57610f9b611ef5565b9050602002810190610fad9190611f26565b91509150610fbd848484846112ed565b848660008051602061248f83398151915286868686604051610fe29493929190611e15565b60405180910390a350505050806001019050610f36565b50611003816113c0565b50505050505050505050565b333014611031573360405163a35b150b60e01b81526004016108c29190611e47565b604051639166d48160e01b815273__$7cc2376e36274fcb28d593438dccae7b38$__90639166d4819061099c907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090899089908990600401611e77565b6110dc8133611203565b50565b6110e882610843565b1561114d5760405162461bcd60e51b815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201526e1c9958591e481cd8da19591d5b1959608a1b60648201526084016108c2565b6002548110156111ae5760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e746044820152652064656c617960d01b60648201526084016108c2565b6111b88142612371565b6000928352600160205260409092209190915550565b60006001600160e01b03198216637965db0b60e01b148061073d57506301ffc9a760e01b6001600160e01b031983161461073d565b61120d8282610c16565b6108d55761121a816114e2565b6112258360206114f4565b604051602001611236929190612384565b60408051601f198184030181529082905262461bcd60e51b82526108c2916004016123f3565b611265826107d4565b6112815760405162461bcd60e51b81526004016108c290612406565b80158061129257506112928161080e565b6108d55760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e6720646570656044820152656e64656e637960d01b60648201526084016108c2565b6000846001600160a01b031684848460405161130a929190612450565b60006040518083038185875af1925050503d8060008114611347576040519150601f19603f3d011682016040523d82523d6000602084013e61134c565b606091505b50509050806113b95760405162461bcd60e51b815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e6720746044820152721c985b9cd858dd1a5bdb881c995d995c9d1959606a1b60648201526084016108c2565b5050505050565b6113c9816107d4565b6113e55760405162461bcd60e51b81526004016108c290612406565b600090815260016020819052604090912055565b6114038282610c16565b6108d5576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556114393390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114878282610c16565b156108d5576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b606061073d6001600160a01b03831660145b60606000611503836002612460565b61150e906002612371565b6001600160401b0381111561152557611525611815565b6040519080825280601f01601f19166020018201604052801561154f576020820181803683370190505b509050600360fc1b8160008151811061156a5761156a611ef5565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061159957611599611ef5565b60200101906001600160f81b031916908160001a90535060006115bd846002612460565b6115c8906001612371565b90505b6001811115611640576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106115fc576115fc611ef5565b1a60f81b82828151811061161257611612611ef5565b60200101906001600160f81b031916908160001a90535060049490941c9361163981612477565b90506115cb565b5083156107f25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108c2565b80356001600160a01b03811681146116a657600080fd5b919050565b60008083601f8401126116bd57600080fd5b5081356001600160401b038111156116d457600080fd5b6020830191508360208285010111156116ec57600080fd5b9250929050565b600080600080600080600060c0888a03121561170e57600080fd5b6117178861168f565b96506020880135955060408801356001600160401b0381111561173957600080fd5b6117458a828b016116ab565b989b979a50986060810135976080820135975060a09091013595509350505050565b60006020828403121561177957600080fd5b81356001600160e01b0319811681146107f257600080fd5b60008060008060008060a087890312156117aa57600080fd5b6117b38761168f565b95506020870135945060408701356001600160401b038111156117d557600080fd5b6117e189828a016116ab565b979a9699509760608101359660809091013595509350505050565b60006020828403121561180e57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561184d5761184d611815565b60405290565b604051601f8201601f191681016001600160401b038111828210171561187b5761187b611815565b604052919050565b600082601f83011261189457600080fd5b81356001600160401b038111156118ad576118ad611815565b6118c0601f8201601f1916602001611853565b8181528460208386010111156118d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561190857600080fd5b6119118561168f565b935061191f6020860161168f565b92506040850135915060608501356001600160401b0381111561194157600080fd5b61194d87828801611883565b91505092959194509250565b6000806040838503121561196c57600080fd5b8235915061197c6020840161168f565b90509250929050565b60008060006060848603121561199a57600080fd5b6119a38461168f565b92506119b16020850161168f565b929592945050506040919091013590565b60008083601f8401126119d457600080fd5b5081356001600160401b038111156119eb57600080fd5b6020830191508360208260051b85010111156116ec57600080fd5b600080600080600080600080600060c08a8c031215611a2457600080fd5b89356001600160401b03811115611a3a57600080fd5b611a468c828d016119c2565b909a5098505060208a01356001600160401b03811115611a6557600080fd5b611a718c828d016119c2565b90985096505060408a01356001600160401b03811115611a9057600080fd5b611a9c8c828d016119c2565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b031215611add57600080fd5b88356001600160401b03811115611af357600080fd5b611aff8b828c016119c2565b90995097505060208901356001600160401b03811115611b1e57600080fd5b611b2a8b828c016119c2565b90975095505060408901356001600160401b03811115611b4957600080fd5b611b558b828c016119c2565b999c989b509699959896976060870135966080013595509350505050565b60006001600160401b03821115611b8c57611b8c611815565b5060051b60200190565b600082601f830112611ba757600080fd5b8135611bba611bb582611b73565b611853565b8082825260208201915060208360051b860101925085831115611bdc57600080fd5b602085015b83811015611bf9578035835260209283019201611be1565b5095945050505050565b600080600080600060a08688031215611c1b57600080fd5b611c248661168f565b9450611c326020870161168f565b935060408601356001600160401b03811115611c4d57600080fd5b611c5988828901611b96565b93505060608601356001600160401b03811115611c7557600080fd5b611c8188828901611b96565b92505060808601356001600160401b03811115611c9d57600080fd5b611ca988828901611883565b9150509295509295909350565b600080600080600080600060c0888a031215611cd157600080fd5b611cda8861168f565b96506020880135955060408801356001600160401b03811115611cfc57600080fd5b611d088a828b016116ab565b909650945050606088013592506080880135915060a08801356001600160401b03811115611d3557600080fd5b88016060818b031215611d4757600080fd5b8091505092959891949750929550565b600080600080600060a08688031215611d6f57600080fd5b611d788661168f565b9450611d866020870161168f565b9350604086013592506060860135915060808601356001600160401b03811115611c9d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201526000611e0060a083018688611daf565b60608301949094525060800152949350505050565b60018060a01b0385168152836020820152606060408201526000611e3d606083018486611daf565b9695505050505050565b6001600160a01b039190911681526040602082018190526004908201526329a2a62360e11b606082015260800190565b6001600160a01b039687168152948616602086015292851660408501529084166060840152909216608082015260a081019190915260c00190565b60208082526023908201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d616040820152620e8c6d60eb1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611f1d57600080fd5b6107f28261168f565b6000808335601e19843603018112611f3d57600080fd5b8301803591506001600160401b03821115611f5757600080fd5b6020019150368190038213156116ec57600080fd5b60008383855260208501945060208460051b8201018360005b86811015611ff957838303601f19018852813536879003601e19018112611fab57600080fd5b86016020810190356001600160401b03811115611fc757600080fd5b803603821315611fd657600080fd5b611fe1858284611daf565b60209a8b019a90955093909301925050600101611f85565b50909695505050505050565b60a0808252810188905260008960c08301825b8b811015612046576001600160a01b036120318461168f565b16825260209283019290910190600101612018565b5083810360208501528881526001600160fb1b0389111561206657600080fd5b8860051b9150818a6020830137018281036020908101604085015261208e9082018789611f6c565b60608401959095525050608001529695505050505050565b600082601f8301126120b757600080fd5b81356120c5611bb582611b73565b8082825260208201915060208360051b8601019250858311156120e757600080fd5b602085015b83811015611bf9576120fd8161168f565b8352602092830192016120ec565b60006060823603121561211d57600080fd5b61212561182b565b82356001600160401b0381111561213b57600080fd5b612147368286016120a6565b82525060208301356001600160401b0381111561216357600080fd5b61216f368286016120a6565b60208301525060408301356001600160401b0381111561218e57600080fd5b830136601f82011261219f57600080fd5b80356121ad611bb582611b73565b8082825260208201915060208360051b8501019250368311156121cf57600080fd5b602084015b838110156122105780356001600160401b038111156121f257600080fd5b61220136602083890101611883565b845250602092830192016121d4565b5060408501525091949350505050565b600081518084526020840193506020830160005b8281101561225b5781516001600160a01b0316865260209586019590910190600101612234565b5093949350505050565b60005b83811015612280578181015183820152602001612268565b50506000910152565b600081518084526122a1816020860160208601612265565b601f01601f19169290920160200192915050565b6020815260008251606060208401526122d16080840182612220565b90506020840151601f198483030160408501526122ee8282612220565b6040860151858203601f190160608701528051808352919350602090810192508084019190600582901b85010160005b8281101561234f57601f1986830301845261233a828651612289565b6020958601959490940193915060010161231e565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561073d5761073d61235b565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516123b6816017850160208801612265565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516123e7816028840160208801612265565b01602801949350505050565b6020815260006107f26020830184612289565b6020808252602a908201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e206973604082015269206e6f7420726561647960b01b606082015260800190565b8183823760009101908152919050565b808202811582820484141761073d5761073d61235b565b6000816124865761248661235b565b50600019019056fec2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e634cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dcafd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78320fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387a2646970667358221220e300d21dcc10a518d439862cbd95c0bbfaa061197c2ee778427b4626af874f8164736f6c634300081d0033", "libraries": { - "PositionImpactPoolUtils": "0x87a0d100b4F9b2A53353974c3596eEC33de8060f" + "PositionImpactPoolUtils": "0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3" }, "devdoc": { "events": { @@ -1491,15 +1491,15 @@ "storageLayout": { "storage": [ { - "astId": 2813, + "astId": 10393, "contract": "contracts/config/ConfigTimelockController.sol:ConfigTimelockController", "label": "_roles", "offset": 0, "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(RoleData)2808_storage)" + "type": "t_mapping(t_bytes32,t_struct(RoleData)10388_storage)" }, { - "astId": 5253, + "astId": 10912, "contract": "contracts/config/ConfigTimelockController.sol:ConfigTimelockController", "label": "_timestamps", "offset": 0, @@ -1507,7 +1507,7 @@ "type": "t_mapping(t_bytes32,t_uint256)" }, { - "astId": 5255, + "astId": 10914, "contract": "contracts/config/ConfigTimelockController.sol:ConfigTimelockController", "label": "_minDelay", "offset": 0, @@ -1538,12 +1538,12 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_bytes32,t_struct(RoleData)2808_storage)": { + "t_mapping(t_bytes32,t_struct(RoleData)10388_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct AccessControl.RoleData)", "numberOfBytes": "32", - "value": "t_struct(RoleData)2808_storage" + "value": "t_struct(RoleData)10388_storage" }, "t_mapping(t_bytes32,t_uint256)": { "encoding": "mapping", @@ -1552,12 +1552,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(RoleData)2808_storage": { + "t_struct(RoleData)10388_storage": { "encoding": "inplace", "label": "struct AccessControl.RoleData", "members": [ { - "astId": 2805, + "astId": 10385, "contract": "contracts/config/ConfigTimelockController.sol:ConfigTimelockController", "label": "members", "offset": 0, @@ -1565,7 +1565,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2807, + "astId": 10387, "contract": "contracts/config/ConfigTimelockController.sol:ConfigTimelockController", "label": "adminRole", "offset": 0, diff --git a/deployments/arbitrum/ContributorHandler.json b/deployments/arbitrum/ContributorHandler.json new file mode 100644 index 000000000..c56bf596f --- /dev/null +++ b/deployments/arbitrum/ContributorHandler.json @@ -0,0 +1,400 @@ +{ + "address": "0x4729D9f61c0159F5e02D2C2e5937B3225e55442C", + "abi": [ + { + "inputs": [ + { + "internalType": "contract RoleStore", + "name": "_roleStore", + "type": "address" + }, + { + "internalType": "contract DataStore", + "name": "_dataStore", + "type": "address" + }, + { + "internalType": "contract EventEmitter", + "name": "_eventEmitter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "InvalidContributorToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokensLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountsLength", + "type": "uint256" + } + ], + "name": "InvalidSetContributorPaymentInput", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokensLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountsLength", + "type": "uint256" + } + ], + "name": "InvalidSetMaxTotalContributorTokenAmountInput", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTotalAmount", + "type": "uint256" + } + ], + "name": "MaxTotalContributorTokenAmountExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "interval", + "type": "uint256" + } + ], + "name": "MinContributorPaymentIntervalBelowAllowedRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minPaymentInterval", + "type": "uint256" + } + ], + "name": "MinContributorPaymentIntervalNotYetPassed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "msgSender", + "type": "address" + }, + { + "internalType": "string", + "name": "role", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "addContributorAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "addContributorToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dataStore", + "outputs": [ + { + "internalType": "contract DataStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eventEmitter", + "outputs": [ + { + "internalType": "contract EventEmitter", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "removeContributorAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "removeContributorToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "roleStore", + "outputs": [ + { + "internalType": "contract RoleStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sendPayments", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "setContributorAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "fundingAccount", + "type": "address" + } + ], + "name": "setContributorFundingAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "fundingAccount", + "type": "address" + } + ], + "name": "setCustomContributorFundingAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "setMaxTotalContributorTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "interval", + "type": "uint256" + } + ], + "name": "setMinContributorPaymentInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xde6ae352e5d1b03bfb58b33f1b62b8842b8f57d0cb146e6094b1e579f1d86a16", + "receipt": { + "to": null, + "from": "0xE7BfFf2aB721264887230037940490351700a068", + "contractAddress": "0x4729D9f61c0159F5e02D2C2e5937B3225e55442C", + "transactionIndex": 1, + "gasUsed": "3024591", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x86b8c0546a2c95c1a4c2cfeafa2d240438208023fc50e404bfb366841a4b90bf", + "transactionHash": "0xde6ae352e5d1b03bfb58b33f1b62b8842b8f57d0cb146e6094b1e579f1d86a16", + "logs": [], + "blockNumber": 390053856, + "cumulativeGasUsed": "3024591", + "status": 1, + "byzantium": true + }, + "args": [ + "0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72", + "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", + "0xC8ee91A54287DB53897056e12D9819156D3822Fb" + ], + "numDeployments": 1, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract RoleStore\",\"name\":\"_roleStore\",\"type\":\"address\"},{\"internalType\":\"contract DataStore\",\"name\":\"_dataStore\",\"type\":\"address\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"_eventEmitter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidContributorToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokensLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountsLength\",\"type\":\"uint256\"}],\"name\":\"InvalidSetContributorPaymentInput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokensLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountsLength\",\"type\":\"uint256\"}],\"name\":\"InvalidSetMaxTotalContributorTokenAmountInput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxTotalAmount\",\"type\":\"uint256\"}],\"name\":\"MaxTotalContributorTokenAmountExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"}],\"name\":\"MinContributorPaymentIntervalBelowAllowedRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minPaymentInterval\",\"type\":\"uint256\"}],\"name\":\"MinContributorPaymentIntervalNotYetPassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"role\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"addContributorAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"addContributorToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dataStore\",\"outputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventEmitter\",\"outputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"removeContributorAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"removeContributorToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"roleStore\",\"outputs\":[{\"internalType\":\"contract RoleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sendPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"setContributorAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fundingAccount\",\"type\":\"address\"}],\"name\":\"setContributorFundingAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fundingAccount\",\"type\":\"address\"}],\"name\":\"setCustomContributorFundingAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"setMaxTotalContributorTokenAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"}],\"name\":\"setMinContributorPaymentInterval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"multicall(bytes[])\":{\"details\":\"Receives and executes a batch of function calls on this contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/contributor/ContributorHandler.sol\":\"ContributorHandler\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0xa535a5df777d44e945dd24aa43a11e44b024140fc340ad0dfe42acf4002aade1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/contributor/ContributorHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/security/ReentrancyGuard.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../utils/BasicMulticall.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\n// @title ContributorHandler\\ncontract ContributorHandler is ReentrancyGuard, RoleModule, BasicMulticall {\\n using SafeERC20 for IERC20;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n\\n constructor(\\n RoleStore _roleStore,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter\\n ) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n }\\n\\n // note that since there will be account * token number of iterations in some functions\\n // and that the CONTRIBUTOR_ACCOUNT_LIST and CONTRIBUTOR_TOKEN_LIST will be loaded entirely\\n // into memory\\n // care should be taken to not have too many accounts / tokens such that the block gas limit\\n // or other execution limits is exceeded\\n function addContributorAccount(address account) external nonReentrant onlyContributorKeeper {\\n dataStore.addAddress(Keys.CONTRIBUTOR_ACCOUNT_LIST, account);\\n }\\n\\n function removeContributorAccount(address account) external nonReentrant onlyContributorKeeper {\\n dataStore.removeAddress(Keys.CONTRIBUTOR_ACCOUNT_LIST, account);\\n }\\n\\n function addContributorToken(address token) external nonReentrant onlyContributorKeeper {\\n dataStore.addAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token);\\n }\\n\\n function removeContributorToken(address token) external nonReentrant onlyContributorKeeper {\\n dataStore.removeAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token);\\n }\\n\\n function setContributorFundingAccount(address token, address fundingAccount) external nonReentrant onlyContributorKeeper {\\n dataStore.setAddress(Keys.contributorFundingAccountKey(token), fundingAccount);\\n }\\n\\n function setCustomContributorFundingAccount(address account, address token, address fundingAccount) external nonReentrant onlyContributorKeeper {\\n dataStore.setAddress(Keys.customContributorFundingAccountKey(account, token), fundingAccount);\\n }\\n\\n function setMinContributorPaymentInterval(uint256 interval) external nonReentrant onlyController {\\n // revert if < 20 days\\n if (interval < 20 days) {\\n revert Errors.MinContributorPaymentIntervalBelowAllowedRange(interval);\\n }\\n\\n dataStore.setUint(Keys.MIN_CONTRIBUTOR_PAYMENT_INTERVAL, interval);\\n }\\n\\n function setMaxTotalContributorTokenAmount(\\n address[] memory tokens,\\n uint256[] memory amounts\\n ) external nonReentrant onlyController {\\n if (tokens.length != amounts.length) {\\n revert Errors.InvalidSetMaxTotalContributorTokenAmountInput(tokens.length, amounts.length);\\n }\\n\\n for (uint256 i; i < tokens.length; i++) {\\n address token = tokens[i];\\n if (!dataStore.containsAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token)) {\\n revert Errors.InvalidContributorToken(token);\\n }\\n dataStore.setUint(Keys.maxTotalContributorTokenAmountKey(token), amounts[i]);\\n }\\n\\n _validateMaxContributorTokenAmounts();\\n }\\n\\n function sendPayments() external nonReentrant onlyContributorDistributor {\\n uint256 lastPaymentAt = dataStore.getUint(Keys.CONTRIBUTOR_LAST_PAYMENT_AT);\\n uint256 minPaymentInterval = dataStore.getUint(Keys.MIN_CONTRIBUTOR_PAYMENT_INTERVAL);\\n\\n if (lastPaymentAt + minPaymentInterval > Chain.currentTimestamp()) {\\n revert Errors.MinContributorPaymentIntervalNotYetPassed(minPaymentInterval);\\n }\\n\\n uint256 tokenCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_TOKEN_LIST);\\n uint256 accountCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_ACCOUNT_LIST);\\n\\n address[] memory tokens = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_TOKEN_LIST, 0, tokenCount);\\n address[] memory accounts = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_ACCOUNT_LIST, 0, accountCount);\\n\\n for (uint256 i; i < tokenCount; i++) {\\n address token = tokens[i];\\n address mainFundingAccount = dataStore.getAddress(Keys.contributorFundingAccountKey(token));\\n\\n for (uint256 j; j < accountCount; j++) {\\n address account = accounts[j];\\n address fundingAccount = dataStore.getAddress(Keys.customContributorFundingAccountKey(account, token));\\n if (fundingAccount == address(0)) {\\n fundingAccount = mainFundingAccount;\\n }\\n\\n uint256 amount = dataStore.getUint(Keys.contributorTokenAmountKey(account, token));\\n\\n IERC20(token).safeTransferFrom(fundingAccount, account, amount);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"fundingAccount\\\", fundingAccount);\\n eventData.addressItems.setItem(1, \\\"account\\\", account);\\n eventData.addressItems.setItem(2, \\\"token\\\", token);\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventEmitter.emitEventLog1(\\n \\\"SendContributorPayment\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n }\\n\\n dataStore.setUint(Keys.CONTRIBUTOR_LAST_PAYMENT_AT, Chain.currentTimestamp());\\n }\\n\\n function setContributorAmount(\\n address account,\\n address[] memory tokens,\\n uint256[] memory amounts\\n ) external nonReentrant onlyContributorKeeper {\\n if (tokens.length != amounts.length) {\\n revert Errors.InvalidSetContributorPaymentInput(tokens.length, amounts.length);\\n }\\n\\n for (uint256 i; i < tokens.length; i++) {\\n address token = tokens[i];\\n if (!dataStore.containsAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token)) {\\n revert Errors.InvalidContributorToken(token);\\n }\\n\\n uint256 amount = amounts[i];\\n dataStore.setUint(Keys.contributorTokenAmountKey(account, token), amount);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventEmitter.emitEventLog1(\\n \\\"SetContributorAmount\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n _validateMaxContributorTokenAmounts();\\n }\\n\\n // note that this is just a sanity validation since the maxTotalContributorTokenAmount\\n // can technically be exceeded since can be separately updated in Config\\n function _validateMaxContributorTokenAmounts() internal view {\\n uint256 tokenCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_TOKEN_LIST);\\n uint256 accountCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_ACCOUNT_LIST);\\n\\n address[] memory tokens = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_TOKEN_LIST, 0, tokenCount);\\n address[] memory accounts = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_ACCOUNT_LIST, 0, accountCount);\\n\\n for (uint256 i; i < tokenCount; i++) {\\n address token = tokens[i];\\n uint256 totalAmount;\\n\\n for (uint256 j; j < accountCount; j++) {\\n address account = accounts[j];\\n uint256 amount = dataStore.getUint(Keys.contributorTokenAmountKey(account, token));\\n totalAmount += amount;\\n }\\n\\n uint256 maxTotalAmount = dataStore.getUint(Keys.maxTotalContributorTokenAmountKey(token));\\n if (totalAmount > maxTotalAmount) {\\n revert Errors.MaxTotalContributorTokenAmountExceeded(token, totalAmount, maxTotalAmount);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaffeca4e31e2b6432acb5b0ca539e5aa1612f92045eb13d141f5718832ca8ae3\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/BasicMulticall.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/ErrorUtils.sol\\\";\\n\\n/**\\n * @title BasicMulticall\\n */\\nabstract contract BasicMulticall {\\n /**\\n * @dev Receives and executes a batch of function calls on this contract.\\n */\\n function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n\\n for (uint256 i; i < data.length; i++) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n ErrorUtils.revertWithParsedMessage(result);\\n }\\n\\n results[i] = result;\\n }\\n\\n return results;\\n }\\n}\\n\",\"keccak256\":\"0xdf9d58a9b7d7b28be24bd2668da62ca377f6e1aa1e65111fd6da7cc6b5db1851\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x60e060405234801561001057600080fd5b5060405161368a38038061368a83398101604081905261002f91610069565b60016000556001600160a01b0392831660805290821660a0521660c0526100b6565b6001600160a01b038116811461006657600080fd5b50565b60008060006060848603121561007e57600080fd5b835161008981610051565b602085015190935061009a81610051565b60408501519092506100ab81610051565b809150509250925092565b60805160a05160c0516134d46101b66000396000818161019101528181610ecf015261163901526000818161013c015281816102a5015281816103c8015281816104de015281816105b001528181610716015281816107cd015281816108b10152818161096801528181610a1f01528181610add01528181610bc401528181610c8801528181610d3501528181610f730152818161105b01528181611119015281816112f50152818161134d015281816113f7015281816114e7015281816116fd0152818161197d01528181611a3401528181611aeb01528181611ba901528181611cba0152611d6d01526000818160ff01526117ae01526134d46000f3fe608060405234801561001057600080fd5b50600436106100ba5760003560e01c80630f8c394b146100bf57806332c9025f146100d457806349f6c644146100e75780634a4a7b04146100fa578063660d0d671461013757806369ad67651461015e5780637a3a988e1461016657806389d6d138146101795780639ff78c301461018c578063ac9650d8146101b3578063d18f9a8f146101d3578063d95205cf146101e6578063f32b56dc146101f9578063f74b76131461020c575b600080fd5b6100d26100cd366004612477565b61021f565b005b6100d26100e23660046124a5565b610366565b6100d26100f536600461262d565b610470565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b60405161012e9190612694565b60405180910390f35b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6100d2610681565b6100d26101743660046126a8565b61103f565b6100d26101873660046126e1565b6110fd565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6101c66101c1366004612705565b6111c5565b60405161012e9190612826565b6100d26101e13660046126e1565b6112d9565b6100d26101f43660046126e1565b611331565b6100d2610207366004612839565b611389565b6100d261021a3660046126e1565b6116e1565b610227611739565b610277604051602001610239906128b2565b604051602081830303815290604052805190602001206040518060400160405280600a81526020016921a7a72a2927a62622a960b11b815250611792565b621a5e008110156102a35760405163961b402560e01b8152600481018290526024015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a6040516020016102e1906128d6565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161031592919061290b565b6020604051808303816000875af1158015610334573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103589190612919565b506103636001600055565b50565b61036e611739565b6103c660405160200161038090612932565b604051602081830303815290604052805190602001206040518060400160405280601281526020017121a7a72a2924a12aaa27a92fa5a2a2a822a960711b815250611792565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca446dd96103ff8585611842565b836040518363ffffffff1660e01b815260040161041d92919061295e565b6020604051808303816000875af115801561043c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104609190612975565b5061046b6001600055565b505050565b610478611739565b61048a604051602001610239906128b2565b80518251146104b25781518151604051630a6a4f7160e21b815260040161029a92919061290b565b60005b825181101561066a5760008382815181106104d2576104d2612992565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c769d1a160405160200161051a906129a8565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161054e92919061295e565b602060405180830381865afa15801561056b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058f91906129d8565b6105ae5780604051634a59130960e01b815260040161029a9190612694565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a6105e6836118e6565b8585815181106105f8576105f8612992565b60200260200101516040518363ffffffff1660e01b815260040161061d92919061290b565b6020604051808303816000875af115801561063c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106609190612919565b50506001016104b5565b50610673611979565b61067d6001600055565b5050565b610689611739565b6107126040516020016106c79060208082526017908201527621a7a72a2924a12aaa27a92fa224a9aa2924a12aaa27a960491b604082015260600190565b604051602081830303815290604052805190602001206040518060400160405280601781526020017621a7a72a2924a12aaa27a92fa224a9aa2924a12aaa27a960491b815250611792565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5604051602001610752906129fa565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161078691815260200190565b602060405180830381865afa1580156107a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c79190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5604051602001610809906128d6565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161083d91815260200190565b602060405180830381865afa15801561085a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087e9190612919565b90504261088b8284612a2f565b11156108ad5760405163b9dc7b9d60e01b81526004810182905260240161029a565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea80596040516020016108ed906129a8565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161092191815260200190565b602060405180830381865afa15801561093e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109629190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea80596040516020016109a490612a50565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016109d891815260200190565b602060405180830381865afa1580156109f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a199190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001610a5b906129a8565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401610a9293929190612a82565b600060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ad79190810190612a98565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001610b1990612a50565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401610b5093929190612a82565b600060405180830381865afa158015610b6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b959190810190612a98565b905060005b84811015610f70576000838281518110610bb657610bb6612992565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166321f8a721610bfa84611e4f565b6040518263ffffffff1660e01b8152600401610c1891815260200190565b602060405180830381865afa158015610c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c599190612975565b905060005b86811015610f65576000858281518110610c7a57610c7a612992565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166321f8a721610cbf8488611842565b6040518263ffffffff1660e01b8152600401610cdd91815260200190565b602060405180830381865afa158015610cfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1e9190612975565b90506001600160a01b038116610d315750825b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5610d6c8589611e90565b6040518263ffffffff1660e01b8152600401610d8a91815260200190565b602060405180830381865afa158015610da7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcb9190612919565b9050610de26001600160a01b038716838584611ece565b610dea612386565b8051610df7906003611f2e565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b60208201528151610e2b9160009086611f93565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151610e589160019087611f93565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610e83916002908a611f93565b6020810151610e93906001611f2e565b610ecd600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151611ff0909392919063ffffffff16565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166324de01e4610f0586612043565b836040518363ffffffff1660e01b8152600401610f239291906132d9565b600060405180830381600087803b158015610f3d57600080fd5b505af1158015610f51573d6000803e3d6000fd5b505060019096019550610c5e945050505050565b505050600101610b9a565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a604051602001610faf906129fa565b60405160208183030381529060405280519060200120610fcc4290565b6040518363ffffffff1660e01b8152600401610fe992919061290b565b6020604051808303816000875af1158015611008573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102c9190612919565b5050505050505061103d6001600055565b565b611047611739565b61105960405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca446dd961109184611e4f565b836040518363ffffffff1660e01b81526004016110af92919061295e565b6020604051808303816000875af11580156110ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f29190612975565b5061067d6001600055565b611105611739565b61111760405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b348e63960405160200161115590612a50565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161118992919061295e565b600060405180830381600087803b1580156111a357600080fd5b505af11580156111b7573d6000803e3d6000fd5b505050506103636001600055565b6060816001600160401b038111156111df576111df6124f0565b60405190808252806020026020018201604052801561121257816020015b60608152602001906001900390816111fd5790505b50905060005b828110156112d1576000803086868581811061123657611236612992565b9050602002810190611248919061331f565b60405161125692919061336c565b600060405180830381855af49150503d8060008114611291576040519150601f19603f3d011682016040523d82523d6000602084013e611296565b606091505b5091509150816112a9576112a98161204f565b808484815181106112bc576112bc612992565b60209081029190910101525050600101611218565b505b92915050565b6112e1611739565b6112f360405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166369721d41604051602001611155906129a8565b611339611739565b61134b60405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166369721d4160405160200161115590612a50565b611391611739565b6113a360405160200161038090612932565b80518251146113cb5781518151604051630530b25960e41b815260040161029a92919061290b565b60005b82518110156116ce5760008382815181106113eb576113eb612992565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c769d1a1604051602001611433906129a8565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161146792919061295e565b602060405180830381865afa158015611484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a891906129d8565b6114c75780604051634a59130960e01b815260040161029a9190612694565b60008383815181106114db576114db612992565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a61151e8885611e90565b836040518363ffffffff1660e01b815260040161153c92919061290b565b6020604051808303816000875af115801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f9190612919565b50611588612386565b8051611595906002611f2e565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516115c2916000908a611f93565b6040805180820190915260058152643a37b5b2b760d91b602082015281516115ed9160019086611f93565b60208101516115fd906001611f2e565b611637600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151611ff0909392919063ffffffff16565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166324de01e461166f89612043565b836040518363ffffffff1660e01b815260040161168d92919061337c565b600060405180830381600087803b1580156116a757600080fd5b505af11580156116bb573d6000803e3d6000fd5b5050600190950194506113ce9350505050565b506116d7611979565b61046b6001600055565b6116e9611739565b6116fb60405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b348e639604051602001611155906129a8565b60026000540361178b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161029a565b6002600055565b60405163ac4ab3fb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ac4ab3fb90604401602060405180830381865afa1580156117fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182191906129d8565b61067d57338160405163a35b150b60e01b815260040161029a9291906133c0565b60006040516020016118909060208082526022908201527f435553544f4d5f434f4e5452494255544f525f46554e44494e475f4143434f55604082015261139560f21b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800160405160208183030381529060405280519060200120905092915050565b60006040516020016119349060208082526022908201527f4d41585f544f54414c5f434f4e5452494255544f525f544f4b454e5f414d4f55604082015261139560f21b606082015260800190565b604051602081830303815290604052805190602001208260405160200161195c92919061295e565b604051602081830303815290604052805190602001209050919050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea80596040516020016119b9906129a8565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016119ed91815260200190565b602060405180830381865afa158015611a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2e9190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea8059604051602001611a7090612a50565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401611aa491815260200190565b602060405180830381865afa158015611ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae59190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001611b27906129a8565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401611b5e93929190612a82565b600060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ba39190810190612a98565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001611be590612a50565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401611c1c93929190612a82565b600060405180830381865afa158015611c39573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c619190810190612a98565b905060005b84811015611e48576000838281518110611c8257611c82612992565b602002602001015190506000805b86811015611d68576000858281518110611cac57611cac612992565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5611cf18488611e90565b6040518263ffffffff1660e01b8152600401611d0f91815260200190565b602060405180830381865afa158015611d2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d509190612919565b9050611d5c8185612a2f565b93505050600101611c90565b5060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5611da3856118e6565b6040518263ffffffff1660e01b8152600401611dc191815260200190565b602060405180830381865afa158015611dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e029190612919565b905080821115611e3d576040516243038f60e41b81526001600160a01b0384166004820152602481018390526044810182905260640161029a565b505050600101611c66565b5050505050565b6000604051602001611934906020808252601b908201527a10d3d395149250955513d497d1955391125391d7d050d0d3d55395602a1b604082015260600190565b60006040516020016118909060208082526018908201527710d3d395149250955513d497d513d2d15397d05353d5539560421b604082015260600190565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611f28908590612088565b50505050565b806001600160401b03811115611f4657611f466124f0565b604051908082528060200260200182016040528015611f8c57816020015b604080518082019091526060815260006020820152815260200190600190039081611f645790505b5090915250565b8184600001518481518110611faa57611faa612992565b6020026020010151600001819052508084600001518481518110611fd057611fd0612992565b6020908102919091018101516001600160a01b0390921691015250505050565b818460000151848151811061200757612007612992565b602002602001015160000181905250808460000151848151811061202d5761202d612992565b6020026020010151602001818152505050505050565b6001600160a01b031690565b60008061205b8361215d565b91509150801561207f578160405162461bcd60e51b815260040161029a91906133e4565b61046b836121ed565b60006120dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121f69092919063ffffffff16565b90508051600014806120fe5750808060200190518101906120fe91906129d8565b61046b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161029a565b60606000604483511015612184575050604080516020810190915260008082529092909150565b6000612191846020015190565b90506307b9e43360e51b6001600160e01b03198216016121d057600484019350838060200190518101906121c591906133f7565b946001945092505050565b600060405180602001604052806000815250909250925050915091565b80518060208301fd5b6060612205848460008561220d565b949350505050565b60608247101561226e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161029a565b600080866001600160a01b0316858760405161228a9190613482565b60006040518083038185875af1925050503d80600081146122c7576040519150601f19603f3d011682016040523d82523d6000602084013e6122cc565b606091505b50915091506122dd878383876122e8565b979650505050505050565b60608315612357578251600003612350576001600160a01b0385163b6123505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161029a565b5081612205565b612205838381511561236c5781518083602001fd5b8060405162461bcd60e51b815260040161029a91906133e4565b604080516101208101909152606060e08201818152610100830191909152819081526020016123c8604051806040016040528060608152602001606081525090565b81526020016123ea604051806040016040528060608152602001606081525090565b815260200161240c604051806040016040528060608152602001606081525090565b815260200161242e604051806040016040528060608152602001606081525090565b8152602001612450604051806040016040528060608152602001606081525090565b8152602001612472604051806040016040528060608152602001606081525090565b905290565b60006020828403121561248957600080fd5b5035919050565b6001600160a01b038116811461036357600080fd5b6000806000606084860312156124ba57600080fd5b83356124c581612490565b925060208401356124d581612490565b915060408401356124e581612490565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561252e5761252e6124f0565b604052919050565b60006001600160401b0382111561254f5761254f6124f0565b5060051b60200190565b600082601f83011261256a57600080fd5b813561257d61257882612536565b612506565b8082825260208201915060208360051b86010192508583111561259f57600080fd5b602085015b838110156125c55780356125b781612490565b8352602092830192016125a4565b5095945050505050565b600082601f8301126125e057600080fd5b81356125ee61257882612536565b8082825260208201915060208360051b86010192508583111561261057600080fd5b602085015b838110156125c5578035835260209283019201612615565b6000806040838503121561264057600080fd5b82356001600160401b0381111561265657600080fd5b61266285828601612559565b92505060208301356001600160401b0381111561267e57600080fd5b61268a858286016125cf565b9150509250929050565b6001600160a01b0391909116815260200190565b600080604083850312156126bb57600080fd5b82356126c681612490565b915060208301356126d681612490565b809150509250929050565b6000602082840312156126f357600080fd5b81356126fe81612490565b9392505050565b6000806020838503121561271857600080fd5b82356001600160401b0381111561272e57600080fd5b8301601f8101851361273f57600080fd5b80356001600160401b0381111561275557600080fd5b8560208260051b840101111561276a57600080fd5b6020919091019590945092505050565b60005b8381101561279557818101518382015260200161277d565b50506000910152565b600081518084526127b681602086016020860161277a565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f1985840301885261280483835161279e565b60209889019890935091909101906001016127e8565b50909695505050505050565b6020815260006126fe60208301846127ca565b60008060006060848603121561284e57600080fd5b833561285981612490565b925060208401356001600160401b0381111561287457600080fd5b61288086828701612559565b92505060408401356001600160401b0381111561289c57600080fd5b6128a8868287016125cf565b9150509250925092565b6020808252600a908201526921a7a72a2927a62622a960b11b604082015260600190565b6020808252818101527f4d494e5f434f4e5452494255544f525f5041594d454e545f494e54455256414c604082015260600190565b918252602082015260400190565b60006020828403121561292b57600080fd5b5051919050565b60208082526012908201527121a7a72a2924a12aaa27a92fa5a2a2a822a960711b604082015260600190565b9182526001600160a01b0316602082015260400190565b60006020828403121561298757600080fd5b81516126fe81612490565b634e487b7160e01b600052603260045260246000fd5b60208082526016908201527510d3d395149250955513d497d513d2d15397d31254d560521b604082015260600190565b6000602082840312156129ea57600080fd5b815180151581146126fe57600080fd5b6020808252601b908201527a10d3d395149250955513d497d31054d517d410565351539517d055602a1b604082015260600190565b808201808211156112d357634e487b7160e01b600052601160045260246000fd5b60208082526018908201527710d3d395149250955513d497d050d0d3d5539517d31254d560421b604082015260600190565b9283526020830191909152604082015260600190565b600060208284031215612aaa57600080fd5b81516001600160401b03811115612ac057600080fd5b8201601f81018413612ad157600080fd5b8051612adf61257882612536565b8082825260208201915060208360051b850101925086831115612b0157600080fd5b6020840193505b82841015612b2c578351612b1b81612490565b825260209384019390910190612b08565b9695505050505050565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612b7a604086018261279e565b6020928301518682038785015280518083529084019360009350909101905b80831015612bc45783516001600160a01b031682526020938401936001939093019290910190612b99565b5060209a8b019a90955093909301925050600101612b54565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612c5757605f198886030183528351805160408752612c2f604088018261279e565b6020928301516001600160a01b03169783019790975250938401939290920191600101612c09565b5050505060208301518482036020860152612c728282612b36565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612cbf604086018261279e565b6020928301518682038785015280518083529084019360009350909101905b80831015612d015783518252602082019150602084019350600183019250612cde565b5060209a8b019a90955093909301925050600101612c99565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612d8b57605f198886030183528351805160408752612d6c604088018261279e565b6020928301519783019790975250938401939290920191600101612d46565b5050505060208301518482036020860152612c728282612c7b565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612d8b57605f198886030183528351805160408752612df8604088018261279e565b6020928301519783019790975250938401939290920191600101612dd2565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612e5b604086018261279e565b6020928301518682038785015280518083529084019360009350909101905b80831015612e9f57835115158252602082019150602084019350600183019250612e7a565b5060209a8b019a90955093909301925050600101612e35565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612f2b57605f198886030183528351805160408752612f0a604088018261279e565b60209283015115159783019790975250938401939290920191600101612ee4565b5050505060208301518482036020860152612c728282612e17565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612d8b57605f198886030183528351805160408752612f98604088018261279e565b6020928301519783019790975250938401939290920191600101612f72565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612ffb604086018261279e565b905060208201519150848103602086015261301681836127ca565b60209a8b019a90955093909301925050600101612fd5565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156130b257605f198886030183528351805160408752613080604088018261279e565b905060208201519150868103602088015261309b818361279e565b96505050602093840193929092019160010161305a565b5050505060208301518482036020860152612c728282612fb7565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552613111604086018261279e565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b8281101561316a57601f1985830301845261315582875161279e565b60209687019694909401939150600101613139565b5080975050505050506020820191506020880197506001810190506130eb565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561320e57605f1988860301835283518051604087526131dc604088018261279e565b90506020820151915086810360208801526131f7818361279e565b9650505060209384019392909201916001016131b6565b5050505060208301518482036020860152612c7282826130cd565b6000815160e0845261323e60e0850182612bdd565b9050602083015184820360208601526132578282612d1a565b915050604083015184820360408601526132718282612da6565b9150506060830151848203606086015261328b8282612eb8565b915050608083015184820360808601526132a58282612f46565b91505060a083015184820360a08601526132bf828261302e565b91505060c083015184820360c0860152612c72828261318a565b60608152601660608201527514d95b9910dbdb9d1c9a589d5d1bdc94185e5b595b9d60521b608082015282602082015260a06040820152600061220560a0830184613229565b6000808335601e1984360301811261333657600080fd5b8301803591506001600160401b0382111561335057600080fd5b60200191503681900382131561336557600080fd5b9250929050565b8183823760009101908152919050565b60608152601460608201527314d95d10dbdb9d1c9a589d5d1bdc905b5bdd5b9d60621b608082015282602082015260a06040820152600061220560a0830184613229565b6001600160a01b03831681526040602082018190526000906122059083018461279e565b6020815260006126fe602083018461279e565b60006020828403121561340957600080fd5b81516001600160401b0381111561341f57600080fd5b8201601f8101841361343057600080fd5b80516001600160401b03811115613449576134496124f0565b61345c601f8201601f1916602001612506565b81815285602083850101111561347157600080fd5b612c7282602083016020860161277a565b6000825161349481846020870161277a565b919091019291505056fea2646970667358221220b149bddee5ebcf1aa6d9d3ebeeaf5a579078e7b94f8f71ddc950a28979b3d74b64736f6c634300081d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ba5760003560e01c80630f8c394b146100bf57806332c9025f146100d457806349f6c644146100e75780634a4a7b04146100fa578063660d0d671461013757806369ad67651461015e5780637a3a988e1461016657806389d6d138146101795780639ff78c301461018c578063ac9650d8146101b3578063d18f9a8f146101d3578063d95205cf146101e6578063f32b56dc146101f9578063f74b76131461020c575b600080fd5b6100d26100cd366004612477565b61021f565b005b6100d26100e23660046124a5565b610366565b6100d26100f536600461262d565b610470565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b60405161012e9190612694565b60405180910390f35b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6100d2610681565b6100d26101743660046126a8565b61103f565b6100d26101873660046126e1565b6110fd565b6101217f000000000000000000000000000000000000000000000000000000000000000081565b6101c66101c1366004612705565b6111c5565b60405161012e9190612826565b6100d26101e13660046126e1565b6112d9565b6100d26101f43660046126e1565b611331565b6100d2610207366004612839565b611389565b6100d261021a3660046126e1565b6116e1565b610227611739565b610277604051602001610239906128b2565b604051602081830303815290604052805190602001206040518060400160405280600a81526020016921a7a72a2927a62622a960b11b815250611792565b621a5e008110156102a35760405163961b402560e01b8152600481018290526024015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a6040516020016102e1906128d6565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161031592919061290b565b6020604051808303816000875af1158015610334573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103589190612919565b506103636001600055565b50565b61036e611739565b6103c660405160200161038090612932565b604051602081830303815290604052805190602001206040518060400160405280601281526020017121a7a72a2924a12aaa27a92fa5a2a2a822a960711b815250611792565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca446dd96103ff8585611842565b836040518363ffffffff1660e01b815260040161041d92919061295e565b6020604051808303816000875af115801561043c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104609190612975565b5061046b6001600055565b505050565b610478611739565b61048a604051602001610239906128b2565b80518251146104b25781518151604051630a6a4f7160e21b815260040161029a92919061290b565b60005b825181101561066a5760008382815181106104d2576104d2612992565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c769d1a160405160200161051a906129a8565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161054e92919061295e565b602060405180830381865afa15801561056b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058f91906129d8565b6105ae5780604051634a59130960e01b815260040161029a9190612694565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a6105e6836118e6565b8585815181106105f8576105f8612992565b60200260200101516040518363ffffffff1660e01b815260040161061d92919061290b565b6020604051808303816000875af115801561063c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106609190612919565b50506001016104b5565b50610673611979565b61067d6001600055565b5050565b610689611739565b6107126040516020016106c79060208082526017908201527621a7a72a2924a12aaa27a92fa224a9aa2924a12aaa27a960491b604082015260600190565b604051602081830303815290604052805190602001206040518060400160405280601781526020017621a7a72a2924a12aaa27a92fa224a9aa2924a12aaa27a960491b815250611792565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5604051602001610752906129fa565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161078691815260200190565b602060405180830381865afa1580156107a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c79190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5604051602001610809906128d6565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161083d91815260200190565b602060405180830381865afa15801561085a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087e9190612919565b90504261088b8284612a2f565b11156108ad5760405163b9dc7b9d60e01b81526004810182905260240161029a565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea80596040516020016108ed906129a8565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161092191815260200190565b602060405180830381865afa15801561093e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109629190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea80596040516020016109a490612a50565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016109d891815260200190565b602060405180830381865afa1580156109f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a199190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001610a5b906129a8565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401610a9293929190612a82565b600060405180830381865afa158015610aaf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ad79190810190612a98565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001610b1990612a50565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401610b5093929190612a82565b600060405180830381865afa158015610b6d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b959190810190612a98565b905060005b84811015610f70576000838281518110610bb657610bb6612992565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166321f8a721610bfa84611e4f565b6040518263ffffffff1660e01b8152600401610c1891815260200190565b602060405180830381865afa158015610c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c599190612975565b905060005b86811015610f65576000858281518110610c7a57610c7a612992565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166321f8a721610cbf8488611842565b6040518263ffffffff1660e01b8152600401610cdd91815260200190565b602060405180830381865afa158015610cfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1e9190612975565b90506001600160a01b038116610d315750825b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5610d6c8589611e90565b6040518263ffffffff1660e01b8152600401610d8a91815260200190565b602060405180830381865afa158015610da7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcb9190612919565b9050610de26001600160a01b038716838584611ece565b610dea612386565b8051610df7906003611f2e565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b60208201528151610e2b9160009086611f93565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151610e589160019087611f93565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610e83916002908a611f93565b6020810151610e93906001611f2e565b610ecd600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151611ff0909392919063ffffffff16565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166324de01e4610f0586612043565b836040518363ffffffff1660e01b8152600401610f239291906132d9565b600060405180830381600087803b158015610f3d57600080fd5b505af1158015610f51573d6000803e3d6000fd5b505060019096019550610c5e945050505050565b505050600101610b9a565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a604051602001610faf906129fa565b60405160208183030381529060405280519060200120610fcc4290565b6040518363ffffffff1660e01b8152600401610fe992919061290b565b6020604051808303816000875af1158015611008573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102c9190612919565b5050505050505061103d6001600055565b565b611047611739565b61105960405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca446dd961109184611e4f565b836040518363ffffffff1660e01b81526004016110af92919061295e565b6020604051808303816000875af11580156110ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f29190612975565b5061067d6001600055565b611105611739565b61111760405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b348e63960405160200161115590612a50565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161118992919061295e565b600060405180830381600087803b1580156111a357600080fd5b505af11580156111b7573d6000803e3d6000fd5b505050506103636001600055565b6060816001600160401b038111156111df576111df6124f0565b60405190808252806020026020018201604052801561121257816020015b60608152602001906001900390816111fd5790505b50905060005b828110156112d1576000803086868581811061123657611236612992565b9050602002810190611248919061331f565b60405161125692919061336c565b600060405180830381855af49150503d8060008114611291576040519150601f19603f3d011682016040523d82523d6000602084013e611296565b606091505b5091509150816112a9576112a98161204f565b808484815181106112bc576112bc612992565b60209081029190910101525050600101611218565b505b92915050565b6112e1611739565b6112f360405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166369721d41604051602001611155906129a8565b611339611739565b61134b60405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166369721d4160405160200161115590612a50565b611391611739565b6113a360405160200161038090612932565b80518251146113cb5781518151604051630530b25960e41b815260040161029a92919061290b565b60005b82518110156116ce5760008382815181106113eb576113eb612992565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c769d1a1604051602001611433906129a8565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161146792919061295e565b602060405180830381865afa158015611484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a891906129d8565b6114c75780604051634a59130960e01b815260040161029a9190612694565b60008383815181106114db576114db612992565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e2a4853a61151e8885611e90565b836040518363ffffffff1660e01b815260040161153c92919061290b565b6020604051808303816000875af115801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f9190612919565b50611588612386565b8051611595906002611f2e565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516115c2916000908a611f93565b6040805180820190915260058152643a37b5b2b760d91b602082015281516115ed9160019086611f93565b60208101516115fd906001611f2e565b611637600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151611ff0909392919063ffffffff16565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166324de01e461166f89612043565b836040518363ffffffff1660e01b815260040161168d92919061337c565b600060405180830381600087803b1580156116a757600080fd5b505af11580156116bb573d6000803e3d6000fd5b5050600190950194506113ce9350505050565b506116d7611979565b61046b6001600055565b6116e9611739565b6116fb60405160200161038090612932565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b348e639604051602001611155906129a8565b60026000540361178b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161029a565b6002600055565b60405163ac4ab3fb60e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ac4ab3fb90604401602060405180830381865afa1580156117fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182191906129d8565b61067d57338160405163a35b150b60e01b815260040161029a9291906133c0565b60006040516020016118909060208082526022908201527f435553544f4d5f434f4e5452494255544f525f46554e44494e475f4143434f55604082015261139560f21b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800160405160208183030381529060405280519060200120905092915050565b60006040516020016119349060208082526022908201527f4d41585f544f54414c5f434f4e5452494255544f525f544f4b454e5f414d4f55604082015261139560f21b606082015260800190565b604051602081830303815290604052805190602001208260405160200161195c92919061295e565b604051602081830303815290604052805190602001209050919050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea80596040516020016119b9906129a8565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016119ed91815260200190565b602060405180830381865afa158015611a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2e9190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335ea8059604051602001611a7090612a50565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401611aa491815260200190565b602060405180830381865afa158015611ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae59190612919565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001611b27906129a8565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401611b5e93929190612a82565b600060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ba39190810190612a98565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7e4148e604051602001611be590612a50565b604051602081830303815290604052805190602001206000866040518463ffffffff1660e01b8152600401611c1c93929190612a82565b600060405180830381865afa158015611c39573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c619190810190612a98565b905060005b84811015611e48576000838281518110611c8257611c82612992565b602002602001015190506000805b86811015611d68576000858281518110611cac57611cac612992565b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5611cf18488611e90565b6040518263ffffffff1660e01b8152600401611d0f91815260200190565b602060405180830381865afa158015611d2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d509190612919565b9050611d5c8185612a2f565b93505050600101611c90565b5060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd02d0f5611da3856118e6565b6040518263ffffffff1660e01b8152600401611dc191815260200190565b602060405180830381865afa158015611dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e029190612919565b905080821115611e3d576040516243038f60e41b81526001600160a01b0384166004820152602481018390526044810182905260640161029a565b505050600101611c66565b5050505050565b6000604051602001611934906020808252601b908201527a10d3d395149250955513d497d1955391125391d7d050d0d3d55395602a1b604082015260600190565b60006040516020016118909060208082526018908201527710d3d395149250955513d497d513d2d15397d05353d5539560421b604082015260600190565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611f28908590612088565b50505050565b806001600160401b03811115611f4657611f466124f0565b604051908082528060200260200182016040528015611f8c57816020015b604080518082019091526060815260006020820152815260200190600190039081611f645790505b5090915250565b8184600001518481518110611faa57611faa612992565b6020026020010151600001819052508084600001518481518110611fd057611fd0612992565b6020908102919091018101516001600160a01b0390921691015250505050565b818460000151848151811061200757612007612992565b602002602001015160000181905250808460000151848151811061202d5761202d612992565b6020026020010151602001818152505050505050565b6001600160a01b031690565b60008061205b8361215d565b91509150801561207f578160405162461bcd60e51b815260040161029a91906133e4565b61046b836121ed565b60006120dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121f69092919063ffffffff16565b90508051600014806120fe5750808060200190518101906120fe91906129d8565b61046b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161029a565b60606000604483511015612184575050604080516020810190915260008082529092909150565b6000612191846020015190565b90506307b9e43360e51b6001600160e01b03198216016121d057600484019350838060200190518101906121c591906133f7565b946001945092505050565b600060405180602001604052806000815250909250925050915091565b80518060208301fd5b6060612205848460008561220d565b949350505050565b60608247101561226e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161029a565b600080866001600160a01b0316858760405161228a9190613482565b60006040518083038185875af1925050503d80600081146122c7576040519150601f19603f3d011682016040523d82523d6000602084013e6122cc565b606091505b50915091506122dd878383876122e8565b979650505050505050565b60608315612357578251600003612350576001600160a01b0385163b6123505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161029a565b5081612205565b612205838381511561236c5781518083602001fd5b8060405162461bcd60e51b815260040161029a91906133e4565b604080516101208101909152606060e08201818152610100830191909152819081526020016123c8604051806040016040528060608152602001606081525090565b81526020016123ea604051806040016040528060608152602001606081525090565b815260200161240c604051806040016040528060608152602001606081525090565b815260200161242e604051806040016040528060608152602001606081525090565b8152602001612450604051806040016040528060608152602001606081525090565b8152602001612472604051806040016040528060608152602001606081525090565b905290565b60006020828403121561248957600080fd5b5035919050565b6001600160a01b038116811461036357600080fd5b6000806000606084860312156124ba57600080fd5b83356124c581612490565b925060208401356124d581612490565b915060408401356124e581612490565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561252e5761252e6124f0565b604052919050565b60006001600160401b0382111561254f5761254f6124f0565b5060051b60200190565b600082601f83011261256a57600080fd5b813561257d61257882612536565b612506565b8082825260208201915060208360051b86010192508583111561259f57600080fd5b602085015b838110156125c55780356125b781612490565b8352602092830192016125a4565b5095945050505050565b600082601f8301126125e057600080fd5b81356125ee61257882612536565b8082825260208201915060208360051b86010192508583111561261057600080fd5b602085015b838110156125c5578035835260209283019201612615565b6000806040838503121561264057600080fd5b82356001600160401b0381111561265657600080fd5b61266285828601612559565b92505060208301356001600160401b0381111561267e57600080fd5b61268a858286016125cf565b9150509250929050565b6001600160a01b0391909116815260200190565b600080604083850312156126bb57600080fd5b82356126c681612490565b915060208301356126d681612490565b809150509250929050565b6000602082840312156126f357600080fd5b81356126fe81612490565b9392505050565b6000806020838503121561271857600080fd5b82356001600160401b0381111561272e57600080fd5b8301601f8101851361273f57600080fd5b80356001600160401b0381111561275557600080fd5b8560208260051b840101111561276a57600080fd5b6020919091019590945092505050565b60005b8381101561279557818101518382015260200161277d565b50506000910152565b600081518084526127b681602086016020860161277a565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f1985840301885261280483835161279e565b60209889019890935091909101906001016127e8565b50909695505050505050565b6020815260006126fe60208301846127ca565b60008060006060848603121561284e57600080fd5b833561285981612490565b925060208401356001600160401b0381111561287457600080fd5b61288086828701612559565b92505060408401356001600160401b0381111561289c57600080fd5b6128a8868287016125cf565b9150509250925092565b6020808252600a908201526921a7a72a2927a62622a960b11b604082015260600190565b6020808252818101527f4d494e5f434f4e5452494255544f525f5041594d454e545f494e54455256414c604082015260600190565b918252602082015260400190565b60006020828403121561292b57600080fd5b5051919050565b60208082526012908201527121a7a72a2924a12aaa27a92fa5a2a2a822a960711b604082015260600190565b9182526001600160a01b0316602082015260400190565b60006020828403121561298757600080fd5b81516126fe81612490565b634e487b7160e01b600052603260045260246000fd5b60208082526016908201527510d3d395149250955513d497d513d2d15397d31254d560521b604082015260600190565b6000602082840312156129ea57600080fd5b815180151581146126fe57600080fd5b6020808252601b908201527a10d3d395149250955513d497d31054d517d410565351539517d055602a1b604082015260600190565b808201808211156112d357634e487b7160e01b600052601160045260246000fd5b60208082526018908201527710d3d395149250955513d497d050d0d3d5539517d31254d560421b604082015260600190565b9283526020830191909152604082015260600190565b600060208284031215612aaa57600080fd5b81516001600160401b03811115612ac057600080fd5b8201601f81018413612ad157600080fd5b8051612adf61257882612536565b8082825260208201915060208360051b850101925086831115612b0157600080fd5b6020840193505b82841015612b2c578351612b1b81612490565b825260209384019390910190612b08565b9695505050505050565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612b7a604086018261279e565b6020928301518682038785015280518083529084019360009350909101905b80831015612bc45783516001600160a01b031682526020938401936001939093019290910190612b99565b5060209a8b019a90955093909301925050600101612b54565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612c5757605f198886030183528351805160408752612c2f604088018261279e565b6020928301516001600160a01b03169783019790975250938401939290920191600101612c09565b5050505060208301518482036020860152612c728282612b36565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612cbf604086018261279e565b6020928301518682038785015280518083529084019360009350909101905b80831015612d015783518252602082019150602084019350600183019250612cde565b5060209a8b019a90955093909301925050600101612c99565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612d8b57605f198886030183528351805160408752612d6c604088018261279e565b6020928301519783019790975250938401939290920191600101612d46565b5050505060208301518482036020860152612c728282612c7b565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612d8b57605f198886030183528351805160408752612df8604088018261279e565b6020928301519783019790975250938401939290920191600101612dd2565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612e5b604086018261279e565b6020928301518682038785015280518083529084019360009350909101905b80831015612e9f57835115158252602082019150602084019350600183019250612e7a565b5060209a8b019a90955093909301925050600101612e35565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612f2b57605f198886030183528351805160408752612f0a604088018261279e565b60209283015115159783019790975250938401939290920191600101612ee4565b5050505060208301518482036020860152612c728282612e17565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015612d8b57605f198886030183528351805160408752612f98604088018261279e565b6020928301519783019790975250938401939290920191600101612f72565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552612ffb604086018261279e565b905060208201519150848103602086015261301681836127ca565b60209a8b019a90955093909301925050600101612fd5565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156130b257605f198886030183528351805160408752613080604088018261279e565b905060208201519150868103602088015261309b818361279e565b96505050602093840193929092019160010161305a565b5050505060208301518482036020860152612c728282612fb7565b600082825180855260208501945060208160051b8301016020850160005b8381101561281a57601f198584030188528151805160408552613111604086018261279e565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b8281101561316a57601f1985830301845261315582875161279e565b60209687019694909401939150600101613139565b5080975050505050506020820191506020880197506001810190506130eb565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561320e57605f1988860301835283518051604087526131dc604088018261279e565b90506020820151915086810360208801526131f7818361279e565b9650505060209384019392909201916001016131b6565b5050505060208301518482036020860152612c7282826130cd565b6000815160e0845261323e60e0850182612bdd565b9050602083015184820360208601526132578282612d1a565b915050604083015184820360408601526132718282612da6565b9150506060830151848203606086015261328b8282612eb8565b915050608083015184820360808601526132a58282612f46565b91505060a083015184820360a08601526132bf828261302e565b91505060c083015184820360c0860152612c72828261318a565b60608152601660608201527514d95b9910dbdb9d1c9a589d5d1bdc94185e5b595b9d60521b608082015282602082015260a06040820152600061220560a0830184613229565b6000808335601e1984360301811261333657600080fd5b8301803591506001600160401b0382111561335057600080fd5b60200191503681900382131561336557600080fd5b9250929050565b8183823760009101908152919050565b60608152601460608201527314d95d10dbdb9d1c9a589d5d1bdc905b5bdd5b9d60621b608082015282602082015260a06040820152600061220560a0830184613229565b6001600160a01b03831681526040602082018190526000906122059083018461279e565b6020815260006126fe602083018461279e565b60006020828403121561340957600080fd5b81516001600160401b0381111561341f57600080fd5b8201601f8101841361343057600080fd5b80516001600160401b03811115613449576134496124f0565b61345c601f8201601f1916602001612506565b81815285602083850101111561347157600080fd5b612c7282602083016020860161277a565b6000825161349481846020870161277a565b919091019291505056fea2646970667358221220b149bddee5ebcf1aa6d9d3ebeeaf5a579078e7b94f8f71ddc950a28979b3d74b64736f6c634300081d0033", + "libraries": {}, + "devdoc": { + "kind": "dev", + "methods": { + "multicall(bytes[])": { + "details": "Receives and executes a batch of function calls on this contract." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 11968, + "contract": "contracts/contributor/ContributorHandler.sol:ContributorHandler", + "label": "_status", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/MarketEventUtils.json b/deployments/arbitrum/MarketEventUtils.json index 113846496..9a564b8fd 100644 --- a/deployments/arbitrum/MarketEventUtils.json +++ b/deployments/arbitrum/MarketEventUtils.json @@ -1,28 +1,28 @@ { - "address": "0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8", + "address": "0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8", "abi": [], - "transactionHash": "0x30d2f00ebc00610e58fd0643551e3c463b4a70ad00f257a66eb90495633f846a", + "transactionHash": "0x69fafc1909fb1660ff6e149d7a2e4c155b790ef8951273b401589466b7e7aaf8", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8", - "transactionIndex": 1, - "gasUsed": "3895045", + "contractAddress": "0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8", + "transactionIndex": 6, + "gasUsed": "3869247", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x36ccb28d849749e64d4887cf2a5bf0aa30da9318cc771ea55f9c8797806bab33", - "transactionHash": "0x30d2f00ebc00610e58fd0643551e3c463b4a70ad00f257a66eb90495633f846a", + "blockHash": "0x116259fd2995e23549434a02fc8058a3d54d314bf5b3687dbb46db7d184ff860", + "transactionHash": "0x69fafc1909fb1660ff6e149d7a2e4c155b790ef8951273b401589466b7e7aaf8", "logs": [], - "blockNumber": 367562372, - "cumulativeGasUsed": "3895045", + "blockNumber": 390053869, + "cumulativeGasUsed": "4418410", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 20, - "solcInputHash": "79ca35a0eb57a5a4e0af2a0fc5a1dbeb", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/MarketEventUtils.sol\":\"MarketEventUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x614464610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106101485760003560e01c8063061034701461014d5780630aa77b6a1461016f578063138231111461018f5780631daaefa1146101af5780631f20ad33146101cf57806328d445cb146101ef578063387a0f131461020f57806340bcc0791461022f57806346ff7f441461024f57806347bc64531461026f5780634c7c4a6d1461028f5780634ddb3d81146102af5780634ee4c831146102cf5780635375a207146102ef578063555a99791461030f5780635bb3aa731461032f5780636d6b20591461034f578063850310d71461036f57806386f48e481461038f5780638983b3ff146103af578063a814bb6f146103cf578063b3d188de146103ef578063d206b7051461040f578063d52463b21461042f578063d791fbb31461044f578063e974c64c1461046f575b600080fd5b81801561015957600080fd5b5061016d610168366004612f1d565b61048f565b005b81801561017b57600080fd5b5061016d61018a366004612f89565b610637565b81801561019b57600080fd5b5061016d6101aa3660046130cb565b61079c565b8180156101bb57600080fd5b5061016d6101ca366004612f89565b610bc1565b8180156101db57600080fd5b5061016d6101ea366004613133565b610cec565b8180156101fb57600080fd5b5061016d61020a366004612f1d565b610ebe565b81801561021b57600080fd5b5061016d61022a3660046131aa565b611032565b81801561023b57600080fd5b5061016d61024a3660046131eb565b61113b565b81801561025b57600080fd5b5061016d61026a3660046131aa565b611257565b81801561027b57600080fd5b5061016d61028a366004612f1d565b61131e565b81801561029b57600080fd5b5061016d6102aa366004613231565b611492565b8180156102bb57600080fd5b5061016d6102ca3660046131eb565b611604565b8180156102db57600080fd5b5061016d6102ea3660046132ab565b611704565b8180156102fb57600080fd5b5061016d61030a3660046131aa565b61188c565b81801561031b57600080fd5b5061016d61032a3660046131eb565b61195f565b81801561033b57600080fd5b5061016d61034a366004613311565b611a5f565b81801561035b57600080fd5b5061016d61036a366004612f1d565b611b4e565b81801561037b57600080fd5b5061016d61038a366004613362565b611cbb565b81801561039b57600080fd5b5061016d6103aa3660046133c7565b611e40565b8180156103bb57600080fd5b5061016d6103ca366004613418565b611f6b565b8180156103db57600080fd5b5061016d6103ea366004613499565b612179565b8180156103fb57600080fd5b5061016d61040a3660046134db565b612307565b81801561041b57600080fd5b5061016d61042a366004613567565b6124ca565b81801561043b57600080fd5b5061016d61044a3660046135a8565b612606565b81801561045b57600080fd5b5061016d61046a366004612f1d565b6129f8565b81801561047b57600080fd5b5061016d61048a3660046131eb565b612b6c565b610497612dff565b80516104a4906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516104d09160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516105059160019088612cee565b6060810151610515906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516105449160009087612d4b565b6020810151610554906002612c89565b61058d60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6105c660016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e46105de88612df3565b836040518363ffffffff1660e01b81526004016105fc929190613cf6565b600060405180830381600087803b15801561061657600080fd5b505af115801561062a573d6000803e3d6000fd5b5050505050505050505050565b61063f612dff565b805161064c906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516106789160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516106a39160019087612cee565b60408101516106b3906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516106df9160009086612da0565b60208101516106ef906001612c89565b61072c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e461074487612df3565b836040518363ffffffff1660e01b8152600401610762929190613d4b565b600060405180830381600087803b15801561077c57600080fd5b505af1158015610790573d6000803e3d6000fd5b50505050505050505050565b6107a4612dff565b60808101516107b4906002612c89565b60408051808201909152600a815269616374696f6e5479706560b01b602082015260808201516107e79160009089612da0565b60408051808201909152600881526774726164654b657960c01b602082015260808201516108189160019088612da0565b8051610825906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516108519160009087612cee565b6040810151610861906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b6020820152845191830151610894929091600091612da0565b6108d36001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b60208201528482015191830151610907929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b602082015260608501519183015161093a929091600391612da0565b602081015161094a906008612c89565b61099160006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b6109d960016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b610a1d60026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b610a6260036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b610aad600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b610afc6005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b610b4560066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b610b8b6007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4610ba386612df3565b836040518363ffffffff1660e01b81526004016105fc929190613d96565b610bc9612dff565b8051610bd6906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610c029160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610c2d9160019087612cee565b6040810151610c3d906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610c699160009086612da0565b6020810151610c79906001612c89565b610cb66000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e4610cce87612df3565b836040518363ffffffff1660e01b8152600401610762929190613ddc565b610cf4612dff565b8051610d01906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610d2d916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610d589160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151610d859160029088612cee565b6020810151610d95906003612c89565b610dce60006040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b610e0b6001604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b610e4c60026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6487612df3565b836040518363ffffffff1660e01b8152600401610e82929190613e1d565b600060405180830381600087803b158015610e9c57600080fd5b505af1158015610eb0573d6000803e3d6000fd5b505050505050505050505050565b610ec6612dff565b8051610ed3906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610eff9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151610f349160019088612cee565b6060810151610f44906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151610f739160009087612d4b565b6040810151610f83906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610faf9160009086612da0565b6020810151610fbf906001612c89565b610ffc6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461101488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613e64565b61103a612dff565b8051611047906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516110739160009086612cee565b6020810151611083906001612c89565b6110cd600060405180604001604052806016815260200175199d5b991a5b99d19858dd1bdc94195c94d958dbdb9960521b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e46110e585612df3565b836040518363ffffffff1660e01b8152600401611103929190613ea7565b600060405180830381600087803b15801561111d57600080fd5b505af1158015611131573d6000803e3d6000fd5b5050505050505050565b611143612dff565b8051611150906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161117c9160009087612cee565b604081015161118c906002612c89565b604080518082018252600581526464656c746160d81b6020820152908201516111b89160009086612da0565b60408051808201825260098152686e65787456616c756560b81b6020820152908201516111e89160019085612da0565b846001600160a01b03166324de01e461120086612df3565b836040518363ffffffff1660e01b815260040161121e929190613ede565b600060405180830381600087803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b505050505050505050565b61125f612dff565b805161126c906001612c89565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516112999160009086612cee565b60208101516112a9906001612c89565b6112e860006040518060400160405280600b81526020016a3ab4a332b2a330b1ba37b960a91b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461130085612df3565b836040518363ffffffff1660e01b8152600401611103929190613f2b565b611326612dff565b8051611333906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161135f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516113949160019088612cee565b60608101516113a4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516113d39160009087612d4b565b60408101516113e3906001612c89565b604080518082018252600581526464656c746160d81b60208201529082015161140f9160009086612da0565b602081015161141f906001612c89565b61145c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461147488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613f6d565b61149a612dff565b80516114a7906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516114d3916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516114fe9160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161152b9160029087612cee565b602081015161153b906003612c89565b61157660006040518060400160405280600781526020016674696d654b657960c81b815250878460200151612da0909392919063ffffffff16565b6115af60016040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6115ec6002604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6486612df3565b61160c612dff565b8051611619906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516116459160009087612cee565b6040810151611655906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516116819160009086612da0565b6020810151611691906001612c89565b6116ce6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e46116e686612df3565b836040518363ffffffff1660e01b815260040161121e929190613fb1565b61170c612dff565b8051611719906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611745916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516117709160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161179d9160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516117cb9160039087612cee565b60208101516117db906002612c89565b611815600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61185660016040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e461186e87612df3565b836040518363ffffffff1660e01b8152600401610e8292919061400a565b611894612dff565b80516118a1906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516118cd9160009086612cee565b60208101516118dd906001612c89565b611929600060405180604001604052806018815260200177189bdc9c9bddda5b99d19858dd1bdc94195c94d958dbdb9960421b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461194185612df3565b836040518363ffffffff1660e01b815260040161110392919061404c565b611967612dff565b8051611974906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516119a09160009087612cee565b60408101516119b0906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516119dc9160009086612da0565b60208101516119ec906001612c89565b611a296000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611a4186612df3565b836040518363ffffffff1660e01b815260040161121e929190614085565b611a67612dff565b8051611a74906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611aa09160009087612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151611ace9160019086612cee565b6020810151611ade906001612c89565b611b18600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611b3086612df3565b836040518363ffffffff1660e01b815260040161121e9291906140d2565b611b56612dff565b8051611b63906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611b8f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151611bc49160019088612cee565b6060810151611bd4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151611c039160009087612d4b565b6020810151611c13906002612c89565b611c4c60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b611c8560016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611c9d88612df3565b836040518363ffffffff1660e01b81526004016105fc92919061411e565b611cc3612dff565b8051611cd0906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611cfc9160009089612cee565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b60208201528151611d309160019088612cee565b6020810151611d40906003612c89565b611d8360006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b815250868460200151612da0909392919063ffffffff16565b611dc760016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b815250858460200151612da0909392919063ffffffff16565b611e0a60026040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611e2288612df3565b836040518363ffffffff1660e01b81526004016105fc929190614178565b611e48612dff565b8051611e55906001612c89565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611e809160009088612cee565b6080810151611e90906001612c89565b60408051808201909152600e81526d1d9a5c9d1d585b151bdad95b925960921b60208201526080820151611ec79160009087612da0565b6040810151611ed7906002612c89565b604080518082018252600581526464656c746160d81b602082015290820151611f039160009086612da0565b60408051808201825260098152686e65787456616c756560b81b602082015290820151611f339160019085612da0565b856001600160a01b03166363d16363611f4b87612df3565b86846040518463ffffffff1660e01b8152600401610762939291906141c1565b611f73612dff565b8051611f80906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611fac916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611fd7916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516120049160029088612cee565b6020810151612014906004612c89565b61204f60006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b61208860016040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b6120c56002604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b61210660036040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e461211e87612df3565b836040518363ffffffff1660e01b815260040161213c929190614214565b600060405180830381600087803b15801561215657600080fd5b505af115801561216a573d6000803e3d6000fd5b50505050505050505050505050565b612181612dff565b805161218e906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516121ba9160009089612cee565b60608101516121ca906001612c89565b60408051808201909152600b81526a34b9a637b733aa37b5b2b760a91b602082015260608201516121fe9160009088612d4b565b608081015161220e906001612c89565b60408051808201909152600f81526e1d9a5c9d1d585b13585c9ad95d1259608a1b602082015260808201516122469160009087612da0565b6040810151612256906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516122829160009086612da0565b6020810151612292906001612c89565b6122cf6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166363d163636122e788612df3565b86846040518463ffffffff1660e01b81526004016105fc9392919061425e565b61230f612dff565b805161231c906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612348916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151612373916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516123a09160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516123ce9160039087612cee565b60208101516123de906003612c89565b61241960006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b612453600160405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61249460026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e46124ac87612df3565b836040518363ffffffff1660e01b815260040161213c9291906142af565b6124d2612dff565b80516124df906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161250b9160009088612cee565b606081015161251b906001612c89565b60408051808201909152600681526569734c6f6e6760d01b6020820152606082015161254a9160009087612d4b565b602081015161255a906002612c89565b61259360006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6125d06001604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46125e887612df3565b836040518363ffffffff1660e01b81526004016107629291906142f0565b61260e612dff565b608081015161261e906001612c89565b60408051808201909152600881526774726164654b657960c01b6020820152608082015161264f9160009088612da0565b805161265c906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126889160009087612cee565b6040810151612698906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b60208201528451918301516126cb929091600091612da0565b61270a6001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b6020820152848201519183015161273e929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b6020820152606085015191830151612771929091600391612da0565b6020810151612781906008612c89565b6127c860006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b61281060016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b61285460026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b61289960036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b6128e4600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b6129336005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b61297c60066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b6129c26007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46129da86612df3565b836040518363ffffffff1660e01b815260040161076292919061433d565b612a00612dff565b8051612a0d906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612a399160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151612a6e9160019088612cee565b6060810151612a7e906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151612aad9160009087612d4b565b6040810151612abd906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151612ae99160009086612da0565b6020810151612af9906001612c89565b612b366000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4612b4e88612df3565b836040518363ffffffff1660e01b81526004016105fc929190614380565b612b74612dff565b8051612b81906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612bad9160009087612cee565b6020810151612bbd906002612c89565b612c03600060405180604001604052806012815260200171191a5cdd1c9a589d5d1a5bdb905b5bdd5b9d60721b815250858460200151612da0909392919063ffffffff16565b612c5360016040518060400160405280601c81526020017b1b995e1d141bdcda5d1a5bdb925b5c1858dd141bdbdb105b5bdd5b9d60221b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4612c6b86612df3565b836040518363ffffffff1660e01b815260040161121e9291906143cb565b806001600160401b03811115612ca157612ca1612fe4565b604051908082528060200260200182016040528015612ce757816020015b604080518082019091526060815260006020820152815260200190600190039081612cbf5790505b5090915250565b8184600001518481518110612d0557612d05614418565b6020026020010151600001819052508084600001518481518110612d2b57612d2b614418565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110612d6257612d62614418565b6020026020010151600001819052508084600001518481518110612d8857612d88614418565b60209081029190910181015191151591015250505050565b8184600001518481518110612db757612db7614418565b6020026020010151600001819052508084600001518481518110612ddd57612ddd614418565b6020026020010151602001818152505050505050565b6001600160a01b031690565b604080516101208101909152606060e0820181815261010083019190915281908152602001612e41604051806040016040528060608152602001606081525090565b8152602001612e63604051806040016040528060608152602001606081525090565b8152602001612e85604051806040016040528060608152602001606081525090565b8152602001612ea7604051806040016040528060608152602001606081525090565b8152602001612ec9604051806040016040528060608152602001606081525090565b8152602001612eeb604051806040016040528060608152602001606081525090565b905290565b6001600160a01b0381168114612f0557600080fd5b50565b80358015158114612f1857600080fd5b919050565b60008060008060008060c08789031215612f3657600080fd5b8635612f4181612ef0565b95506020870135612f5181612ef0565b94506040870135612f6181612ef0565b9350612f6f60608801612f08565b9598949750929560808101359460a0909101359350915050565b600080600080600060a08688031215612fa157600080fd5b8535612fac81612ef0565b94506020860135612fbc81612ef0565b93506040860135612fcc81612ef0565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b038111828210171561302b57634e487b7160e01b600052604160045260246000fd5b60405290565b6000610180828403121561304457600080fd5b61304c612ffa565b823581526020808401359082015260408084013590820152606080840135908201526080808401359082015260a0808401359082015260c0808401359082015260e08084013590820152610100808401359082015261012080840135908201526101408084013590820152610160928301359281019290925250919050565b60008060008060008061022087890312156130e557600080fd5b86356130f081612ef0565b95506020870135945060408701359350606087013561310e81612ef0565b925061311d8860808901613031565b9598949750929591949361020090920135925050565b600080600080600080600060e0888a03121561314e57600080fd5b873561315981612ef0565b9650602088013561316981612ef0565b9550604088013561317981612ef0565b9450606088013561318981612ef0565b9699959850939660808101359560a0820135955060c0909101359350915050565b6000806000606084860312156131bf57600080fd5b83356131ca81612ef0565b925060208401356131da81612ef0565b929592945050506040919091013590565b6000806000806080858703121561320157600080fd5b843561320c81612ef0565b9350602085013561321c81612ef0565b93969395505050506040820135916060013590565b600080600080600080600060e0888a03121561324c57600080fd5b873561325781612ef0565b9650602088013561326781612ef0565b9550604088013561327781612ef0565b945060608801359350608088013561328e81612ef0565b9699959850939692959460a0840135945060c09093013592915050565b600080600080600080600060e0888a0312156132c657600080fd5b87356132d181612ef0565b965060208801356132e181612ef0565b955060408801356132f181612ef0565b9450606088013561330181612ef0565b9350608088013561328e81612ef0565b6000806000806080858703121561332757600080fd5b843561333281612ef0565b9350602085013561334281612ef0565b9250604085013561335281612ef0565b9396929550929360600135925050565b60008060008060008060c0878903121561337b57600080fd5b863561338681612ef0565b9550602087013561339681612ef0565b945060408701356133a681612ef0565b959894975094956060810135955060808101359460a0909101359350915050565b600080600080600060a086880312156133df57600080fd5b85356133ea81612ef0565b945060208601356133fa81612ef0565b94979496505050506040830135926060810135926080909101359150565b600080600080600080600080610100898b03121561343557600080fd5b883561344081612ef0565b9750602089013561345081612ef0565b9650604089013561346081612ef0565b955060608901359450608089013561347781612ef0565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60008060008060008060c087890312156134b257600080fd5b86356134bd81612ef0565b955060208701356134cd81612ef0565b94506133a660408801612f08565b600080600080600080600080610100898b0312156134f857600080fd5b883561350381612ef0565b9750602089013561351381612ef0565b9650604089013561352381612ef0565b955060608901359450608089013561353a81612ef0565b935060a089013561354a81612ef0565b979a969950949793969295929450505060c08201359160e0013590565b600080600080600060a0868803121561357f57600080fd5b853561358a81612ef0565b9450602086013561359a81612ef0565b9350612fcc60408701612f08565b600080600080600061020086880312156135c157600080fd5b85356135cc81612ef0565b94506020860135935060408601356135e381612ef0565b92506135f28760608801613031565b949793965091946101e0013592915050565b6000815180845260005b8181101561362a5760208185018101518683018201520161360e565b506000602082860101526020601f19601f83011685010191505092915050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261368e6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156136d85783516001600160a01b0316825260209384019360019390930192909101906136ad565b5060209a8b019a90955093909301925050600101613668565b50909695505050505050565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561377757605f19888603018352835180516040875261374f6040880182613604565b6020928301516001600160a01b03169783019790975250938401939290920191600101613729565b5050505060208301518482036020860152613792828261364a565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f1985840301885281518051604085526137df6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b8083101561382157835182526020820191506020840193506001830192506137fe565b5060209a8b019a909550939093019250506001016137b9565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f19888603018352835180516040875261388c6040880182613604565b6020928301519783019790975250938401939290920191600101613866565b5050505060208301518482036020860152613792828261379b565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f1988860301835283518051604087526139186040880182613604565b60209283015197830197909752509384019392909201916001016138f2565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261397b6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156139bf5783511515825260208201915060208401935060018301925061399a565b5060209a8b019a90955093909301925050600101613955565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613a4b57605f198886030183528351805160408752613a2a6040880182613604565b60209283015115159783019790975250938401939290920191600101613a04565b50505050602083015184820360208601526137928282613937565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f198584030188528151805160408552613aaa6040860182613604565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b82811015613b0357601f19858303018452613aee828751613604565b60209687019694909401939150600101613ad2565b508097505050505050602082019150602088019750600181019050613a84565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613b756040880182613604565b9050602082015191508681036020880152613b908183613604565b965050506020938401939290920191600101613b4f565b50505050602083015184820360208601526137928282613a66565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613c146040880182613604565b9050602082015191508681036020880152613c2f8183613604565b965050506020938401939290920191600101613bee565b6000815160e08452613c5b60e08501826136fd565b905060208301518482036020860152613c74828261383a565b91505060408301518482036040860152613c8e82826138c6565b91505060608301518482036060860152613ca882826139d8565b91505060808301518482036080860152613cc282826138c6565b91505060a083015184820360a0860152613cdc8282613b23565b91505060c083015184820360c08601526137928282613bc2565b60608152601e60608201527f46756e64696e67466565416d6f756e7450657253697a65557064617465640000608082015282602082015260a060408201526000613d4360a0830184613c46565b949350505050565b60608152601b60608201527a14ddd85c125b5c1858dd141bdbdb105b5bdd5b9d155c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601660608201527513585c9ad95d141bdbdb15985b1d59555c19185d195960521b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526011606082015270141bdbdb105b5bdd5b9d155c19185d1959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601760608201527610db185a5b58589b19519d5b991a5b99d55c19185d1959604a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601360608201527213dc195b925b9d195c995cdd155c19185d1959606a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152600760608201526646756e64696e6760c81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f546f74616c50656e64696e67496d70616374416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526012606082015271155a519959519858dd1bdc955c19185d195960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601460608201527310dbdb1b185d195c985b14dd5b555c19185d195960621b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602360608201527f4c656e74506f736974696f6e496d70616374506f6f6c416d6f756e74557064616080820152621d195960ea1b60a082015282602082015260c060408201526000613d4360c0830184613c46565b606081526012606082015271119d5b991a5b99d199595cd0db185a5b595960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526009606082015268426f72726f77696e6760b81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f506f736974696f6e496d70616374506f6f6c416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601c60608201527b141bdcda5d1a5bdb925b5c1858dd141bdbdb15da5d1a191c985dd85b60221b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602460608201527f436c61696d61626c6546756e64696e67416d6f756e7450657253697a65557064608082015263185d195960e21b60a082015282602082015260c060408201526000613d4360c0830184613c46565b6060815260196060820152782632b73a24b6b830b1ba20b6b7bab73a2932b23ab1ba34b7b760391b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601f60808201527f5669727475616c506f736974696f6e496e76656e746f7279557064617465640060a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601a60608201527910db185a5b58589b1950dbdb1b185d195c985b155c19185d195960321b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601b60808201527a159a5c9d1d585b14ddd85c125b9d995b9d1bdc9e555c19185d1959602a1b60a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601160608201527010dbdb1b185d195c985b10db185a5b5959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602060608201527f43756d756c6174697665426f72726f77696e67466163746f7255706461746564608082015282602082015260a060408201526000613d4360a0830184613c46565b6060815260136060820152724d61726b6574506f6f6c56616c7565496e666f60681b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601b60608201527a13dc195b925b9d195c995cdd125b951bdad95b9cd55c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601d60608201527f506f736974696f6e496d70616374506f6f6c4469737472696275746564000000608082015282602082015260a060408201526000613d4360a0830184613c46565b634e487b7160e01b600052603260045260246000fdfea26469706673582212200b5f170258c56f9eb9f61c3c7aa4df0644dfff064105b63e98d3ba706a7d2b3d64736f6c634300081d0033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106101485760003560e01c8063061034701461014d5780630aa77b6a1461016f578063138231111461018f5780631daaefa1146101af5780631f20ad33146101cf57806328d445cb146101ef578063387a0f131461020f57806340bcc0791461022f57806346ff7f441461024f57806347bc64531461026f5780634c7c4a6d1461028f5780634ddb3d81146102af5780634ee4c831146102cf5780635375a207146102ef578063555a99791461030f5780635bb3aa731461032f5780636d6b20591461034f578063850310d71461036f57806386f48e481461038f5780638983b3ff146103af578063a814bb6f146103cf578063b3d188de146103ef578063d206b7051461040f578063d52463b21461042f578063d791fbb31461044f578063e974c64c1461046f575b600080fd5b81801561015957600080fd5b5061016d610168366004612f1d565b61048f565b005b81801561017b57600080fd5b5061016d61018a366004612f89565b610637565b81801561019b57600080fd5b5061016d6101aa3660046130cb565b61079c565b8180156101bb57600080fd5b5061016d6101ca366004612f89565b610bc1565b8180156101db57600080fd5b5061016d6101ea366004613133565b610cec565b8180156101fb57600080fd5b5061016d61020a366004612f1d565b610ebe565b81801561021b57600080fd5b5061016d61022a3660046131aa565b611032565b81801561023b57600080fd5b5061016d61024a3660046131eb565b61113b565b81801561025b57600080fd5b5061016d61026a3660046131aa565b611257565b81801561027b57600080fd5b5061016d61028a366004612f1d565b61131e565b81801561029b57600080fd5b5061016d6102aa366004613231565b611492565b8180156102bb57600080fd5b5061016d6102ca3660046131eb565b611604565b8180156102db57600080fd5b5061016d6102ea3660046132ab565b611704565b8180156102fb57600080fd5b5061016d61030a3660046131aa565b61188c565b81801561031b57600080fd5b5061016d61032a3660046131eb565b61195f565b81801561033b57600080fd5b5061016d61034a366004613311565b611a5f565b81801561035b57600080fd5b5061016d61036a366004612f1d565b611b4e565b81801561037b57600080fd5b5061016d61038a366004613362565b611cbb565b81801561039b57600080fd5b5061016d6103aa3660046133c7565b611e40565b8180156103bb57600080fd5b5061016d6103ca366004613418565b611f6b565b8180156103db57600080fd5b5061016d6103ea366004613499565b612179565b8180156103fb57600080fd5b5061016d61040a3660046134db565b612307565b81801561041b57600080fd5b5061016d61042a366004613567565b6124ca565b81801561043b57600080fd5b5061016d61044a3660046135a8565b612606565b81801561045b57600080fd5b5061016d61046a366004612f1d565b6129f8565b81801561047b57600080fd5b5061016d61048a3660046131eb565b612b6c565b610497612dff565b80516104a4906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516104d09160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516105059160019088612cee565b6060810151610515906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516105449160009087612d4b565b6020810151610554906002612c89565b61058d60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6105c660016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e46105de88612df3565b836040518363ffffffff1660e01b81526004016105fc929190613cf6565b600060405180830381600087803b15801561061657600080fd5b505af115801561062a573d6000803e3d6000fd5b5050505050505050505050565b61063f612dff565b805161064c906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516106789160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516106a39160019087612cee565b60408101516106b3906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516106df9160009086612da0565b60208101516106ef906001612c89565b61072c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e461074487612df3565b836040518363ffffffff1660e01b8152600401610762929190613d4b565b600060405180830381600087803b15801561077c57600080fd5b505af1158015610790573d6000803e3d6000fd5b50505050505050505050565b6107a4612dff565b60808101516107b4906002612c89565b60408051808201909152600a815269616374696f6e5479706560b01b602082015260808201516107e79160009089612da0565b60408051808201909152600881526774726164654b657960c01b602082015260808201516108189160019088612da0565b8051610825906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516108519160009087612cee565b6040810151610861906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b6020820152845191830151610894929091600091612da0565b6108d36001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b60208201528482015191830151610907929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b602082015260608501519183015161093a929091600391612da0565b602081015161094a906008612c89565b61099160006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b6109d960016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b610a1d60026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b610a6260036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b610aad600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b610afc6005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b610b4560066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b610b8b6007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4610ba386612df3565b836040518363ffffffff1660e01b81526004016105fc929190613d96565b610bc9612dff565b8051610bd6906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610c029160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610c2d9160019087612cee565b6040810151610c3d906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610c699160009086612da0565b6020810151610c79906001612c89565b610cb66000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e4610cce87612df3565b836040518363ffffffff1660e01b8152600401610762929190613ddc565b610cf4612dff565b8051610d01906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610d2d916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610d589160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151610d859160029088612cee565b6020810151610d95906003612c89565b610dce60006040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b610e0b6001604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b610e4c60026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6487612df3565b836040518363ffffffff1660e01b8152600401610e82929190613e1d565b600060405180830381600087803b158015610e9c57600080fd5b505af1158015610eb0573d6000803e3d6000fd5b505050505050505050505050565b610ec6612dff565b8051610ed3906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610eff9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151610f349160019088612cee565b6060810151610f44906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151610f739160009087612d4b565b6040810151610f83906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610faf9160009086612da0565b6020810151610fbf906001612c89565b610ffc6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461101488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613e64565b61103a612dff565b8051611047906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516110739160009086612cee565b6020810151611083906001612c89565b6110cd600060405180604001604052806016815260200175199d5b991a5b99d19858dd1bdc94195c94d958dbdb9960521b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e46110e585612df3565b836040518363ffffffff1660e01b8152600401611103929190613ea7565b600060405180830381600087803b15801561111d57600080fd5b505af1158015611131573d6000803e3d6000fd5b5050505050505050565b611143612dff565b8051611150906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161117c9160009087612cee565b604081015161118c906002612c89565b604080518082018252600581526464656c746160d81b6020820152908201516111b89160009086612da0565b60408051808201825260098152686e65787456616c756560b81b6020820152908201516111e89160019085612da0565b846001600160a01b03166324de01e461120086612df3565b836040518363ffffffff1660e01b815260040161121e929190613ede565b600060405180830381600087803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b505050505050505050565b61125f612dff565b805161126c906001612c89565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516112999160009086612cee565b60208101516112a9906001612c89565b6112e860006040518060400160405280600b81526020016a3ab4a332b2a330b1ba37b960a91b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461130085612df3565b836040518363ffffffff1660e01b8152600401611103929190613f2b565b611326612dff565b8051611333906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161135f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516113949160019088612cee565b60608101516113a4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516113d39160009087612d4b565b60408101516113e3906001612c89565b604080518082018252600581526464656c746160d81b60208201529082015161140f9160009086612da0565b602081015161141f906001612c89565b61145c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461147488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613f6d565b61149a612dff565b80516114a7906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516114d3916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516114fe9160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161152b9160029087612cee565b602081015161153b906003612c89565b61157660006040518060400160405280600781526020016674696d654b657960c81b815250878460200151612da0909392919063ffffffff16565b6115af60016040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6115ec6002604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6486612df3565b61160c612dff565b8051611619906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516116459160009087612cee565b6040810151611655906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516116819160009086612da0565b6020810151611691906001612c89565b6116ce6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e46116e686612df3565b836040518363ffffffff1660e01b815260040161121e929190613fb1565b61170c612dff565b8051611719906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611745916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516117709160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161179d9160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516117cb9160039087612cee565b60208101516117db906002612c89565b611815600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61185660016040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e461186e87612df3565b836040518363ffffffff1660e01b8152600401610e8292919061400a565b611894612dff565b80516118a1906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516118cd9160009086612cee565b60208101516118dd906001612c89565b611929600060405180604001604052806018815260200177189bdc9c9bddda5b99d19858dd1bdc94195c94d958dbdb9960421b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461194185612df3565b836040518363ffffffff1660e01b815260040161110392919061404c565b611967612dff565b8051611974906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516119a09160009087612cee565b60408101516119b0906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516119dc9160009086612da0565b60208101516119ec906001612c89565b611a296000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611a4186612df3565b836040518363ffffffff1660e01b815260040161121e929190614085565b611a67612dff565b8051611a74906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611aa09160009087612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151611ace9160019086612cee565b6020810151611ade906001612c89565b611b18600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611b3086612df3565b836040518363ffffffff1660e01b815260040161121e9291906140d2565b611b56612dff565b8051611b63906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611b8f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151611bc49160019088612cee565b6060810151611bd4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151611c039160009087612d4b565b6020810151611c13906002612c89565b611c4c60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b611c8560016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611c9d88612df3565b836040518363ffffffff1660e01b81526004016105fc92919061411e565b611cc3612dff565b8051611cd0906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611cfc9160009089612cee565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b60208201528151611d309160019088612cee565b6020810151611d40906003612c89565b611d8360006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b815250868460200151612da0909392919063ffffffff16565b611dc760016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b815250858460200151612da0909392919063ffffffff16565b611e0a60026040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611e2288612df3565b836040518363ffffffff1660e01b81526004016105fc929190614178565b611e48612dff565b8051611e55906001612c89565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611e809160009088612cee565b6080810151611e90906001612c89565b60408051808201909152600e81526d1d9a5c9d1d585b151bdad95b925960921b60208201526080820151611ec79160009087612da0565b6040810151611ed7906002612c89565b604080518082018252600581526464656c746160d81b602082015290820151611f039160009086612da0565b60408051808201825260098152686e65787456616c756560b81b602082015290820151611f339160019085612da0565b856001600160a01b03166363d16363611f4b87612df3565b86846040518463ffffffff1660e01b8152600401610762939291906141c1565b611f73612dff565b8051611f80906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611fac916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611fd7916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516120049160029088612cee565b6020810151612014906004612c89565b61204f60006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b61208860016040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b6120c56002604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b61210660036040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e461211e87612df3565b836040518363ffffffff1660e01b815260040161213c929190614214565b600060405180830381600087803b15801561215657600080fd5b505af115801561216a573d6000803e3d6000fd5b50505050505050505050505050565b612181612dff565b805161218e906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516121ba9160009089612cee565b60608101516121ca906001612c89565b60408051808201909152600b81526a34b9a637b733aa37b5b2b760a91b602082015260608201516121fe9160009088612d4b565b608081015161220e906001612c89565b60408051808201909152600f81526e1d9a5c9d1d585b13585c9ad95d1259608a1b602082015260808201516122469160009087612da0565b6040810151612256906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516122829160009086612da0565b6020810151612292906001612c89565b6122cf6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166363d163636122e788612df3565b86846040518463ffffffff1660e01b81526004016105fc9392919061425e565b61230f612dff565b805161231c906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612348916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151612373916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516123a09160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516123ce9160039087612cee565b60208101516123de906003612c89565b61241960006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b612453600160405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61249460026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e46124ac87612df3565b836040518363ffffffff1660e01b815260040161213c9291906142af565b6124d2612dff565b80516124df906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161250b9160009088612cee565b606081015161251b906001612c89565b60408051808201909152600681526569734c6f6e6760d01b6020820152606082015161254a9160009087612d4b565b602081015161255a906002612c89565b61259360006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6125d06001604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46125e887612df3565b836040518363ffffffff1660e01b81526004016107629291906142f0565b61260e612dff565b608081015161261e906001612c89565b60408051808201909152600881526774726164654b657960c01b6020820152608082015161264f9160009088612da0565b805161265c906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126889160009087612cee565b6040810151612698906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b60208201528451918301516126cb929091600091612da0565b61270a6001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b6020820152848201519183015161273e929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b6020820152606085015191830151612771929091600391612da0565b6020810151612781906008612c89565b6127c860006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b61281060016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b61285460026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b61289960036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b6128e4600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b6129336005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b61297c60066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b6129c26007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46129da86612df3565b836040518363ffffffff1660e01b815260040161076292919061433d565b612a00612dff565b8051612a0d906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612a399160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151612a6e9160019088612cee565b6060810151612a7e906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151612aad9160009087612d4b565b6040810151612abd906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151612ae99160009086612da0565b6020810151612af9906001612c89565b612b366000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4612b4e88612df3565b836040518363ffffffff1660e01b81526004016105fc929190614380565b612b74612dff565b8051612b81906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612bad9160009087612cee565b6020810151612bbd906002612c89565b612c03600060405180604001604052806012815260200171191a5cdd1c9a589d5d1a5bdb905b5bdd5b9d60721b815250858460200151612da0909392919063ffffffff16565b612c5360016040518060400160405280601c81526020017b1b995e1d141bdcda5d1a5bdb925b5c1858dd141bdbdb105b5bdd5b9d60221b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4612c6b86612df3565b836040518363ffffffff1660e01b815260040161121e9291906143cb565b806001600160401b03811115612ca157612ca1612fe4565b604051908082528060200260200182016040528015612ce757816020015b604080518082019091526060815260006020820152815260200190600190039081612cbf5790505b5090915250565b8184600001518481518110612d0557612d05614418565b6020026020010151600001819052508084600001518481518110612d2b57612d2b614418565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110612d6257612d62614418565b6020026020010151600001819052508084600001518481518110612d8857612d88614418565b60209081029190910181015191151591015250505050565b8184600001518481518110612db757612db7614418565b6020026020010151600001819052508084600001518481518110612ddd57612ddd614418565b6020026020010151602001818152505050505050565b6001600160a01b031690565b604080516101208101909152606060e0820181815261010083019190915281908152602001612e41604051806040016040528060608152602001606081525090565b8152602001612e63604051806040016040528060608152602001606081525090565b8152602001612e85604051806040016040528060608152602001606081525090565b8152602001612ea7604051806040016040528060608152602001606081525090565b8152602001612ec9604051806040016040528060608152602001606081525090565b8152602001612eeb604051806040016040528060608152602001606081525090565b905290565b6001600160a01b0381168114612f0557600080fd5b50565b80358015158114612f1857600080fd5b919050565b60008060008060008060c08789031215612f3657600080fd5b8635612f4181612ef0565b95506020870135612f5181612ef0565b94506040870135612f6181612ef0565b9350612f6f60608801612f08565b9598949750929560808101359460a0909101359350915050565b600080600080600060a08688031215612fa157600080fd5b8535612fac81612ef0565b94506020860135612fbc81612ef0565b93506040860135612fcc81612ef0565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b038111828210171561302b57634e487b7160e01b600052604160045260246000fd5b60405290565b6000610180828403121561304457600080fd5b61304c612ffa565b823581526020808401359082015260408084013590820152606080840135908201526080808401359082015260a0808401359082015260c0808401359082015260e08084013590820152610100808401359082015261012080840135908201526101408084013590820152610160928301359281019290925250919050565b60008060008060008061022087890312156130e557600080fd5b86356130f081612ef0565b95506020870135945060408701359350606087013561310e81612ef0565b925061311d8860808901613031565b9598949750929591949361020090920135925050565b600080600080600080600060e0888a03121561314e57600080fd5b873561315981612ef0565b9650602088013561316981612ef0565b9550604088013561317981612ef0565b9450606088013561318981612ef0565b9699959850939660808101359560a0820135955060c0909101359350915050565b6000806000606084860312156131bf57600080fd5b83356131ca81612ef0565b925060208401356131da81612ef0565b929592945050506040919091013590565b6000806000806080858703121561320157600080fd5b843561320c81612ef0565b9350602085013561321c81612ef0565b93969395505050506040820135916060013590565b600080600080600080600060e0888a03121561324c57600080fd5b873561325781612ef0565b9650602088013561326781612ef0565b9550604088013561327781612ef0565b945060608801359350608088013561328e81612ef0565b9699959850939692959460a0840135945060c09093013592915050565b600080600080600080600060e0888a0312156132c657600080fd5b87356132d181612ef0565b965060208801356132e181612ef0565b955060408801356132f181612ef0565b9450606088013561330181612ef0565b9350608088013561328e81612ef0565b6000806000806080858703121561332757600080fd5b843561333281612ef0565b9350602085013561334281612ef0565b9250604085013561335281612ef0565b9396929550929360600135925050565b60008060008060008060c0878903121561337b57600080fd5b863561338681612ef0565b9550602087013561339681612ef0565b945060408701356133a681612ef0565b959894975094956060810135955060808101359460a0909101359350915050565b600080600080600060a086880312156133df57600080fd5b85356133ea81612ef0565b945060208601356133fa81612ef0565b94979496505050506040830135926060810135926080909101359150565b600080600080600080600080610100898b03121561343557600080fd5b883561344081612ef0565b9750602089013561345081612ef0565b9650604089013561346081612ef0565b955060608901359450608089013561347781612ef0565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60008060008060008060c087890312156134b257600080fd5b86356134bd81612ef0565b955060208701356134cd81612ef0565b94506133a660408801612f08565b600080600080600080600080610100898b0312156134f857600080fd5b883561350381612ef0565b9750602089013561351381612ef0565b9650604089013561352381612ef0565b955060608901359450608089013561353a81612ef0565b935060a089013561354a81612ef0565b979a969950949793969295929450505060c08201359160e0013590565b600080600080600060a0868803121561357f57600080fd5b853561358a81612ef0565b9450602086013561359a81612ef0565b9350612fcc60408701612f08565b600080600080600061020086880312156135c157600080fd5b85356135cc81612ef0565b94506020860135935060408601356135e381612ef0565b92506135f28760608801613031565b949793965091946101e0013592915050565b6000815180845260005b8181101561362a5760208185018101518683018201520161360e565b506000602082860101526020601f19601f83011685010191505092915050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261368e6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156136d85783516001600160a01b0316825260209384019360019390930192909101906136ad565b5060209a8b019a90955093909301925050600101613668565b50909695505050505050565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561377757605f19888603018352835180516040875261374f6040880182613604565b6020928301516001600160a01b03169783019790975250938401939290920191600101613729565b5050505060208301518482036020860152613792828261364a565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f1985840301885281518051604085526137df6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b8083101561382157835182526020820191506020840193506001830192506137fe565b5060209a8b019a909550939093019250506001016137b9565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f19888603018352835180516040875261388c6040880182613604565b6020928301519783019790975250938401939290920191600101613866565b5050505060208301518482036020860152613792828261379b565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f1988860301835283518051604087526139186040880182613604565b60209283015197830197909752509384019392909201916001016138f2565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261397b6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156139bf5783511515825260208201915060208401935060018301925061399a565b5060209a8b019a90955093909301925050600101613955565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613a4b57605f198886030183528351805160408752613a2a6040880182613604565b60209283015115159783019790975250938401939290920191600101613a04565b50505050602083015184820360208601526137928282613937565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f198584030188528151805160408552613aaa6040860182613604565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b82811015613b0357601f19858303018452613aee828751613604565b60209687019694909401939150600101613ad2565b508097505050505050602082019150602088019750600181019050613a84565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613b756040880182613604565b9050602082015191508681036020880152613b908183613604565b965050506020938401939290920191600101613b4f565b50505050602083015184820360208601526137928282613a66565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613c146040880182613604565b9050602082015191508681036020880152613c2f8183613604565b965050506020938401939290920191600101613bee565b6000815160e08452613c5b60e08501826136fd565b905060208301518482036020860152613c74828261383a565b91505060408301518482036040860152613c8e82826138c6565b91505060608301518482036060860152613ca882826139d8565b91505060808301518482036080860152613cc282826138c6565b91505060a083015184820360a0860152613cdc8282613b23565b91505060c083015184820360c08601526137928282613bc2565b60608152601e60608201527f46756e64696e67466565416d6f756e7450657253697a65557064617465640000608082015282602082015260a060408201526000613d4360a0830184613c46565b949350505050565b60608152601b60608201527a14ddd85c125b5c1858dd141bdbdb105b5bdd5b9d155c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601660608201527513585c9ad95d141bdbdb15985b1d59555c19185d195960521b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526011606082015270141bdbdb105b5bdd5b9d155c19185d1959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601760608201527610db185a5b58589b19519d5b991a5b99d55c19185d1959604a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601360608201527213dc195b925b9d195c995cdd155c19185d1959606a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152600760608201526646756e64696e6760c81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f546f74616c50656e64696e67496d70616374416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526012606082015271155a519959519858dd1bdc955c19185d195960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601460608201527310dbdb1b185d195c985b14dd5b555c19185d195960621b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602360608201527f4c656e74506f736974696f6e496d70616374506f6f6c416d6f756e74557064616080820152621d195960ea1b60a082015282602082015260c060408201526000613d4360c0830184613c46565b606081526012606082015271119d5b991a5b99d199595cd0db185a5b595960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526009606082015268426f72726f77696e6760b81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f506f736974696f6e496d70616374506f6f6c416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601c60608201527b141bdcda5d1a5bdb925b5c1858dd141bdbdb15da5d1a191c985dd85b60221b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602460608201527f436c61696d61626c6546756e64696e67416d6f756e7450657253697a65557064608082015263185d195960e21b60a082015282602082015260c060408201526000613d4360c0830184613c46565b6060815260196060820152782632b73a24b6b830b1ba20b6b7bab73a2932b23ab1ba34b7b760391b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601f60808201527f5669727475616c506f736974696f6e496e76656e746f7279557064617465640060a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601a60608201527910db185a5b58589b1950dbdb1b185d195c985b155c19185d195960321b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601b60808201527a159a5c9d1d585b14ddd85c125b9d995b9d1bdc9e555c19185d1959602a1b60a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601160608201527010dbdb1b185d195c985b10db185a5b5959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602060608201527f43756d756c6174697665426f72726f77696e67466163746f7255706461746564608082015282602082015260a060408201526000613d4360a0830184613c46565b6060815260136060820152724d61726b6574506f6f6c56616c7565496e666f60681b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601b60608201527a13dc195b925b9d195c995cdd125b951bdad95b9cd55c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601d60608201527f506f736974696f6e496d70616374506f6f6c4469737472696275746564000000608082015282602082015260a060408201526000613d4360a0830184613c46565b634e487b7160e01b600052603260045260246000fdfea26469706673582212200b5f170258c56f9eb9f61c3c7aa4df0644dfff064105b63e98d3ba706a7d2b3d64736f6c634300081d0033", + "numDeployments": 21, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/MarketEventUtils.sol\":\"MarketEventUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x614464610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106101485760003560e01c8063061034701461014d5780630aa77b6a1461016f578063138231111461018f5780631daaefa1146101af5780631f20ad33146101cf57806328d445cb146101ef578063387a0f131461020f57806340bcc0791461022f57806346ff7f441461024f57806347bc64531461026f5780634c7c4a6d1461028f5780634ddb3d81146102af5780634ee4c831146102cf5780635375a207146102ef578063555a99791461030f5780635bb3aa731461032f5780636d6b20591461034f578063850310d71461036f57806386f48e481461038f5780638983b3ff146103af578063a814bb6f146103cf578063b3d188de146103ef578063d206b7051461040f578063d52463b21461042f578063d791fbb31461044f578063e974c64c1461046f575b600080fd5b81801561015957600080fd5b5061016d610168366004612f1d565b61048f565b005b81801561017b57600080fd5b5061016d61018a366004612f89565b610637565b81801561019b57600080fd5b5061016d6101aa3660046130cb565b61079c565b8180156101bb57600080fd5b5061016d6101ca366004612f89565b610bc1565b8180156101db57600080fd5b5061016d6101ea366004613133565b610cec565b8180156101fb57600080fd5b5061016d61020a366004612f1d565b610ebe565b81801561021b57600080fd5b5061016d61022a3660046131aa565b611032565b81801561023b57600080fd5b5061016d61024a3660046131eb565b61113b565b81801561025b57600080fd5b5061016d61026a3660046131aa565b611257565b81801561027b57600080fd5b5061016d61028a366004612f1d565b61131e565b81801561029b57600080fd5b5061016d6102aa366004613231565b611492565b8180156102bb57600080fd5b5061016d6102ca3660046131eb565b611604565b8180156102db57600080fd5b5061016d6102ea3660046132ab565b611704565b8180156102fb57600080fd5b5061016d61030a3660046131aa565b61188c565b81801561031b57600080fd5b5061016d61032a3660046131eb565b61195f565b81801561033b57600080fd5b5061016d61034a366004613311565b611a5f565b81801561035b57600080fd5b5061016d61036a366004612f1d565b611b4e565b81801561037b57600080fd5b5061016d61038a366004613362565b611cbb565b81801561039b57600080fd5b5061016d6103aa3660046133c7565b611e40565b8180156103bb57600080fd5b5061016d6103ca366004613418565b611f6b565b8180156103db57600080fd5b5061016d6103ea366004613499565b612179565b8180156103fb57600080fd5b5061016d61040a3660046134db565b612307565b81801561041b57600080fd5b5061016d61042a366004613567565b6124ca565b81801561043b57600080fd5b5061016d61044a3660046135a8565b612606565b81801561045b57600080fd5b5061016d61046a366004612f1d565b6129f8565b81801561047b57600080fd5b5061016d61048a3660046131eb565b612b6c565b610497612dff565b80516104a4906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516104d09160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516105059160019088612cee565b6060810151610515906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516105449160009087612d4b565b6020810151610554906002612c89565b61058d60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6105c660016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e46105de88612df3565b836040518363ffffffff1660e01b81526004016105fc929190613cf6565b600060405180830381600087803b15801561061657600080fd5b505af115801561062a573d6000803e3d6000fd5b5050505050505050505050565b61063f612dff565b805161064c906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516106789160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516106a39160019087612cee565b60408101516106b3906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516106df9160009086612da0565b60208101516106ef906001612c89565b61072c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e461074487612df3565b836040518363ffffffff1660e01b8152600401610762929190613d4b565b600060405180830381600087803b15801561077c57600080fd5b505af1158015610790573d6000803e3d6000fd5b50505050505050505050565b6107a4612dff565b60808101516107b4906002612c89565b60408051808201909152600a815269616374696f6e5479706560b01b602082015260808201516107e79160009089612da0565b60408051808201909152600881526774726164654b657960c01b602082015260808201516108189160019088612da0565b8051610825906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516108519160009087612cee565b6040810151610861906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b6020820152845191830151610894929091600091612da0565b6108d36001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b60208201528482015191830151610907929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b602082015260608501519183015161093a929091600391612da0565b602081015161094a906008612c89565b61099160006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b6109d960016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b610a1d60026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b610a6260036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b610aad600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b610afc6005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b610b4560066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b610b8b6007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4610ba386612df3565b836040518363ffffffff1660e01b81526004016105fc929190613d96565b610bc9612dff565b8051610bd6906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610c029160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610c2d9160019087612cee565b6040810151610c3d906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610c699160009086612da0565b6020810151610c79906001612c89565b610cb66000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e4610cce87612df3565b836040518363ffffffff1660e01b8152600401610762929190613ddc565b610cf4612dff565b8051610d01906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610d2d916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610d589160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151610d859160029088612cee565b6020810151610d95906003612c89565b610dce60006040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b610e0b6001604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b610e4c60026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6487612df3565b836040518363ffffffff1660e01b8152600401610e82929190613e1d565b600060405180830381600087803b158015610e9c57600080fd5b505af1158015610eb0573d6000803e3d6000fd5b505050505050505050505050565b610ec6612dff565b8051610ed3906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610eff9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151610f349160019088612cee565b6060810151610f44906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151610f739160009087612d4b565b6040810151610f83906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610faf9160009086612da0565b6020810151610fbf906001612c89565b610ffc6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461101488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613e64565b61103a612dff565b8051611047906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516110739160009086612cee565b6020810151611083906001612c89565b6110cd600060405180604001604052806016815260200175199d5b991a5b99d19858dd1bdc94195c94d958dbdb9960521b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e46110e585612df3565b836040518363ffffffff1660e01b8152600401611103929190613ea7565b600060405180830381600087803b15801561111d57600080fd5b505af1158015611131573d6000803e3d6000fd5b5050505050505050565b611143612dff565b8051611150906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161117c9160009087612cee565b604081015161118c906002612c89565b604080518082018252600581526464656c746160d81b6020820152908201516111b89160009086612da0565b60408051808201825260098152686e65787456616c756560b81b6020820152908201516111e89160019085612da0565b846001600160a01b03166324de01e461120086612df3565b836040518363ffffffff1660e01b815260040161121e929190613ede565b600060405180830381600087803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b505050505050505050565b61125f612dff565b805161126c906001612c89565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516112999160009086612cee565b60208101516112a9906001612c89565b6112e860006040518060400160405280600b81526020016a3ab4a332b2a330b1ba37b960a91b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461130085612df3565b836040518363ffffffff1660e01b8152600401611103929190613f2b565b611326612dff565b8051611333906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161135f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516113949160019088612cee565b60608101516113a4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516113d39160009087612d4b565b60408101516113e3906001612c89565b604080518082018252600581526464656c746160d81b60208201529082015161140f9160009086612da0565b602081015161141f906001612c89565b61145c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461147488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613f6d565b61149a612dff565b80516114a7906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516114d3916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516114fe9160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161152b9160029087612cee565b602081015161153b906003612c89565b61157660006040518060400160405280600781526020016674696d654b657960c81b815250878460200151612da0909392919063ffffffff16565b6115af60016040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6115ec6002604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6486612df3565b61160c612dff565b8051611619906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516116459160009087612cee565b6040810151611655906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516116819160009086612da0565b6020810151611691906001612c89565b6116ce6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e46116e686612df3565b836040518363ffffffff1660e01b815260040161121e929190613fb1565b61170c612dff565b8051611719906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611745916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516117709160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161179d9160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516117cb9160039087612cee565b60208101516117db906002612c89565b611815600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61185660016040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e461186e87612df3565b836040518363ffffffff1660e01b8152600401610e8292919061400a565b611894612dff565b80516118a1906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516118cd9160009086612cee565b60208101516118dd906001612c89565b611929600060405180604001604052806018815260200177189bdc9c9bddda5b99d19858dd1bdc94195c94d958dbdb9960421b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461194185612df3565b836040518363ffffffff1660e01b815260040161110392919061404c565b611967612dff565b8051611974906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516119a09160009087612cee565b60408101516119b0906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516119dc9160009086612da0565b60208101516119ec906001612c89565b611a296000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611a4186612df3565b836040518363ffffffff1660e01b815260040161121e929190614085565b611a67612dff565b8051611a74906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611aa09160009087612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151611ace9160019086612cee565b6020810151611ade906001612c89565b611b18600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611b3086612df3565b836040518363ffffffff1660e01b815260040161121e9291906140d2565b611b56612dff565b8051611b63906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611b8f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151611bc49160019088612cee565b6060810151611bd4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151611c039160009087612d4b565b6020810151611c13906002612c89565b611c4c60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b611c8560016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611c9d88612df3565b836040518363ffffffff1660e01b81526004016105fc92919061411e565b611cc3612dff565b8051611cd0906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611cfc9160009089612cee565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b60208201528151611d309160019088612cee565b6020810151611d40906003612c89565b611d8360006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b815250868460200151612da0909392919063ffffffff16565b611dc760016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b815250858460200151612da0909392919063ffffffff16565b611e0a60026040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611e2288612df3565b836040518363ffffffff1660e01b81526004016105fc929190614178565b611e48612dff565b8051611e55906001612c89565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611e809160009088612cee565b6080810151611e90906001612c89565b60408051808201909152600e81526d1d9a5c9d1d585b151bdad95b925960921b60208201526080820151611ec79160009087612da0565b6040810151611ed7906002612c89565b604080518082018252600581526464656c746160d81b602082015290820151611f039160009086612da0565b60408051808201825260098152686e65787456616c756560b81b602082015290820151611f339160019085612da0565b856001600160a01b03166363d16363611f4b87612df3565b86846040518463ffffffff1660e01b8152600401610762939291906141c1565b611f73612dff565b8051611f80906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611fac916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611fd7916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516120049160029088612cee565b6020810151612014906004612c89565b61204f60006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b61208860016040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b6120c56002604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b61210660036040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e461211e87612df3565b836040518363ffffffff1660e01b815260040161213c929190614214565b600060405180830381600087803b15801561215657600080fd5b505af115801561216a573d6000803e3d6000fd5b50505050505050505050505050565b612181612dff565b805161218e906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516121ba9160009089612cee565b60608101516121ca906001612c89565b60408051808201909152600b81526a34b9a637b733aa37b5b2b760a91b602082015260608201516121fe9160009088612d4b565b608081015161220e906001612c89565b60408051808201909152600f81526e1d9a5c9d1d585b13585c9ad95d1259608a1b602082015260808201516122469160009087612da0565b6040810151612256906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516122829160009086612da0565b6020810151612292906001612c89565b6122cf6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166363d163636122e788612df3565b86846040518463ffffffff1660e01b81526004016105fc9392919061425e565b61230f612dff565b805161231c906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612348916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151612373916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516123a09160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516123ce9160039087612cee565b60208101516123de906003612c89565b61241960006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b612453600160405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61249460026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e46124ac87612df3565b836040518363ffffffff1660e01b815260040161213c9291906142af565b6124d2612dff565b80516124df906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161250b9160009088612cee565b606081015161251b906001612c89565b60408051808201909152600681526569734c6f6e6760d01b6020820152606082015161254a9160009087612d4b565b602081015161255a906002612c89565b61259360006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6125d06001604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46125e887612df3565b836040518363ffffffff1660e01b81526004016107629291906142f0565b61260e612dff565b608081015161261e906001612c89565b60408051808201909152600881526774726164654b657960c01b6020820152608082015161264f9160009088612da0565b805161265c906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126889160009087612cee565b6040810151612698906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b60208201528451918301516126cb929091600091612da0565b61270a6001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b6020820152848201519183015161273e929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b6020820152606085015191830151612771929091600391612da0565b6020810151612781906008612c89565b6127c860006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b61281060016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b61285460026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b61289960036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b6128e4600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b6129336005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b61297c60066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b6129c26007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46129da86612df3565b836040518363ffffffff1660e01b815260040161076292919061433d565b612a00612dff565b8051612a0d906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612a399160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151612a6e9160019088612cee565b6060810151612a7e906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151612aad9160009087612d4b565b6040810151612abd906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151612ae99160009086612da0565b6020810151612af9906001612c89565b612b366000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4612b4e88612df3565b836040518363ffffffff1660e01b81526004016105fc929190614380565b612b74612dff565b8051612b81906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612bad9160009087612cee565b6020810151612bbd906002612c89565b612c03600060405180604001604052806012815260200171191a5cdd1c9a589d5d1a5bdb905b5bdd5b9d60721b815250858460200151612da0909392919063ffffffff16565b612c5360016040518060400160405280601c81526020017b1b995e1d141bdcda5d1a5bdb925b5c1858dd141bdbdb105b5bdd5b9d60221b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4612c6b86612df3565b836040518363ffffffff1660e01b815260040161121e9291906143cb565b806001600160401b03811115612ca157612ca1612fe4565b604051908082528060200260200182016040528015612ce757816020015b604080518082019091526060815260006020820152815260200190600190039081612cbf5790505b5090915250565b8184600001518481518110612d0557612d05614418565b6020026020010151600001819052508084600001518481518110612d2b57612d2b614418565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110612d6257612d62614418565b6020026020010151600001819052508084600001518481518110612d8857612d88614418565b60209081029190910181015191151591015250505050565b8184600001518481518110612db757612db7614418565b6020026020010151600001819052508084600001518481518110612ddd57612ddd614418565b6020026020010151602001818152505050505050565b6001600160a01b031690565b604080516101208101909152606060e0820181815261010083019190915281908152602001612e41604051806040016040528060608152602001606081525090565b8152602001612e63604051806040016040528060608152602001606081525090565b8152602001612e85604051806040016040528060608152602001606081525090565b8152602001612ea7604051806040016040528060608152602001606081525090565b8152602001612ec9604051806040016040528060608152602001606081525090565b8152602001612eeb604051806040016040528060608152602001606081525090565b905290565b6001600160a01b0381168114612f0557600080fd5b50565b80358015158114612f1857600080fd5b919050565b60008060008060008060c08789031215612f3657600080fd5b8635612f4181612ef0565b95506020870135612f5181612ef0565b94506040870135612f6181612ef0565b9350612f6f60608801612f08565b9598949750929560808101359460a0909101359350915050565b600080600080600060a08688031215612fa157600080fd5b8535612fac81612ef0565b94506020860135612fbc81612ef0565b93506040860135612fcc81612ef0565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b038111828210171561302b57634e487b7160e01b600052604160045260246000fd5b60405290565b6000610180828403121561304457600080fd5b61304c612ffa565b823581526020808401359082015260408084013590820152606080840135908201526080808401359082015260a0808401359082015260c0808401359082015260e08084013590820152610100808401359082015261012080840135908201526101408084013590820152610160928301359281019290925250919050565b60008060008060008061022087890312156130e557600080fd5b86356130f081612ef0565b95506020870135945060408701359350606087013561310e81612ef0565b925061311d8860808901613031565b9598949750929591949361020090920135925050565b600080600080600080600060e0888a03121561314e57600080fd5b873561315981612ef0565b9650602088013561316981612ef0565b9550604088013561317981612ef0565b9450606088013561318981612ef0565b9699959850939660808101359560a0820135955060c0909101359350915050565b6000806000606084860312156131bf57600080fd5b83356131ca81612ef0565b925060208401356131da81612ef0565b929592945050506040919091013590565b6000806000806080858703121561320157600080fd5b843561320c81612ef0565b9350602085013561321c81612ef0565b93969395505050506040820135916060013590565b600080600080600080600060e0888a03121561324c57600080fd5b873561325781612ef0565b9650602088013561326781612ef0565b9550604088013561327781612ef0565b945060608801359350608088013561328e81612ef0565b9699959850939692959460a0840135945060c09093013592915050565b600080600080600080600060e0888a0312156132c657600080fd5b87356132d181612ef0565b965060208801356132e181612ef0565b955060408801356132f181612ef0565b9450606088013561330181612ef0565b9350608088013561328e81612ef0565b6000806000806080858703121561332757600080fd5b843561333281612ef0565b9350602085013561334281612ef0565b9250604085013561335281612ef0565b9396929550929360600135925050565b60008060008060008060c0878903121561337b57600080fd5b863561338681612ef0565b9550602087013561339681612ef0565b945060408701356133a681612ef0565b959894975094956060810135955060808101359460a0909101359350915050565b600080600080600060a086880312156133df57600080fd5b85356133ea81612ef0565b945060208601356133fa81612ef0565b94979496505050506040830135926060810135926080909101359150565b600080600080600080600080610100898b03121561343557600080fd5b883561344081612ef0565b9750602089013561345081612ef0565b9650604089013561346081612ef0565b955060608901359450608089013561347781612ef0565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60008060008060008060c087890312156134b257600080fd5b86356134bd81612ef0565b955060208701356134cd81612ef0565b94506133a660408801612f08565b600080600080600080600080610100898b0312156134f857600080fd5b883561350381612ef0565b9750602089013561351381612ef0565b9650604089013561352381612ef0565b955060608901359450608089013561353a81612ef0565b935060a089013561354a81612ef0565b979a969950949793969295929450505060c08201359160e0013590565b600080600080600060a0868803121561357f57600080fd5b853561358a81612ef0565b9450602086013561359a81612ef0565b9350612fcc60408701612f08565b600080600080600061020086880312156135c157600080fd5b85356135cc81612ef0565b94506020860135935060408601356135e381612ef0565b92506135f28760608801613031565b949793965091946101e0013592915050565b6000815180845260005b8181101561362a5760208185018101518683018201520161360e565b506000602082860101526020601f19601f83011685010191505092915050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261368e6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156136d85783516001600160a01b0316825260209384019360019390930192909101906136ad565b5060209a8b019a90955093909301925050600101613668565b50909695505050505050565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561377757605f19888603018352835180516040875261374f6040880182613604565b6020928301516001600160a01b03169783019790975250938401939290920191600101613729565b5050505060208301518482036020860152613792828261364a565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f1985840301885281518051604085526137df6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b8083101561382157835182526020820191506020840193506001830192506137fe565b5060209a8b019a909550939093019250506001016137b9565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f19888603018352835180516040875261388c6040880182613604565b6020928301519783019790975250938401939290920191600101613866565b5050505060208301518482036020860152613792828261379b565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f1988860301835283518051604087526139186040880182613604565b60209283015197830197909752509384019392909201916001016138f2565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261397b6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156139bf5783511515825260208201915060208401935060018301925061399a565b5060209a8b019a90955093909301925050600101613955565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613a4b57605f198886030183528351805160408752613a2a6040880182613604565b60209283015115159783019790975250938401939290920191600101613a04565b50505050602083015184820360208601526137928282613937565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f198584030188528151805160408552613aaa6040860182613604565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b82811015613b0357601f19858303018452613aee828751613604565b60209687019694909401939150600101613ad2565b508097505050505050602082019150602088019750600181019050613a84565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613b756040880182613604565b9050602082015191508681036020880152613b908183613604565b965050506020938401939290920191600101613b4f565b50505050602083015184820360208601526137928282613a66565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613c146040880182613604565b9050602082015191508681036020880152613c2f8183613604565b965050506020938401939290920191600101613bee565b6000815160e08452613c5b60e08501826136fd565b905060208301518482036020860152613c74828261383a565b91505060408301518482036040860152613c8e82826138c6565b91505060608301518482036060860152613ca882826139d8565b91505060808301518482036080860152613cc282826138c6565b91505060a083015184820360a0860152613cdc8282613b23565b91505060c083015184820360c08601526137928282613bc2565b60608152601e60608201527f46756e64696e67466565416d6f756e7450657253697a65557064617465640000608082015282602082015260a060408201526000613d4360a0830184613c46565b949350505050565b60608152601b60608201527a14ddd85c125b5c1858dd141bdbdb105b5bdd5b9d155c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601660608201527513585c9ad95d141bdbdb15985b1d59555c19185d195960521b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526011606082015270141bdbdb105b5bdd5b9d155c19185d1959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601760608201527610db185a5b58589b19519d5b991a5b99d55c19185d1959604a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601360608201527213dc195b925b9d195c995cdd155c19185d1959606a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152600760608201526646756e64696e6760c81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f546f74616c50656e64696e67496d70616374416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526012606082015271155a519959519858dd1bdc955c19185d195960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601460608201527310dbdb1b185d195c985b14dd5b555c19185d195960621b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602360608201527f4c656e74506f736974696f6e496d70616374506f6f6c416d6f756e74557064616080820152621d195960ea1b60a082015282602082015260c060408201526000613d4360c0830184613c46565b606081526012606082015271119d5b991a5b99d199595cd0db185a5b595960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526009606082015268426f72726f77696e6760b81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f506f736974696f6e496d70616374506f6f6c416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601c60608201527b141bdcda5d1a5bdb925b5c1858dd141bdbdb15da5d1a191c985dd85b60221b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602460608201527f436c61696d61626c6546756e64696e67416d6f756e7450657253697a65557064608082015263185d195960e21b60a082015282602082015260c060408201526000613d4360c0830184613c46565b6060815260196060820152782632b73a24b6b830b1ba20b6b7bab73a2932b23ab1ba34b7b760391b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601f60808201527f5669727475616c506f736974696f6e496e76656e746f7279557064617465640060a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601a60608201527910db185a5b58589b1950dbdb1b185d195c985b155c19185d195960321b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601b60808201527a159a5c9d1d585b14ddd85c125b9d995b9d1bdc9e555c19185d1959602a1b60a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601160608201527010dbdb1b185d195c985b10db185a5b5959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602060608201527f43756d756c6174697665426f72726f77696e67466163746f7255706461746564608082015282602082015260a060408201526000613d4360a0830184613c46565b6060815260136060820152724d61726b6574506f6f6c56616c7565496e666f60681b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601b60608201527a13dc195b925b9d195c995cdd125b951bdad95b9cd55c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601d60608201527f506f736974696f6e496d70616374506f6f6c4469737472696275746564000000608082015282602082015260a060408201526000613d4360a0830184613c46565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220d11068c55b5896d32d6994095243826d6b989a41cc34fe6ac3818f26df692dd564736f6c634300081d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106101485760003560e01c8063061034701461014d5780630aa77b6a1461016f578063138231111461018f5780631daaefa1146101af5780631f20ad33146101cf57806328d445cb146101ef578063387a0f131461020f57806340bcc0791461022f57806346ff7f441461024f57806347bc64531461026f5780634c7c4a6d1461028f5780634ddb3d81146102af5780634ee4c831146102cf5780635375a207146102ef578063555a99791461030f5780635bb3aa731461032f5780636d6b20591461034f578063850310d71461036f57806386f48e481461038f5780638983b3ff146103af578063a814bb6f146103cf578063b3d188de146103ef578063d206b7051461040f578063d52463b21461042f578063d791fbb31461044f578063e974c64c1461046f575b600080fd5b81801561015957600080fd5b5061016d610168366004612f1d565b61048f565b005b81801561017b57600080fd5b5061016d61018a366004612f89565b610637565b81801561019b57600080fd5b5061016d6101aa3660046130cb565b61079c565b8180156101bb57600080fd5b5061016d6101ca366004612f89565b610bc1565b8180156101db57600080fd5b5061016d6101ea366004613133565b610cec565b8180156101fb57600080fd5b5061016d61020a366004612f1d565b610ebe565b81801561021b57600080fd5b5061016d61022a3660046131aa565b611032565b81801561023b57600080fd5b5061016d61024a3660046131eb565b61113b565b81801561025b57600080fd5b5061016d61026a3660046131aa565b611257565b81801561027b57600080fd5b5061016d61028a366004612f1d565b61131e565b81801561029b57600080fd5b5061016d6102aa366004613231565b611492565b8180156102bb57600080fd5b5061016d6102ca3660046131eb565b611604565b8180156102db57600080fd5b5061016d6102ea3660046132ab565b611704565b8180156102fb57600080fd5b5061016d61030a3660046131aa565b61188c565b81801561031b57600080fd5b5061016d61032a3660046131eb565b61195f565b81801561033b57600080fd5b5061016d61034a366004613311565b611a5f565b81801561035b57600080fd5b5061016d61036a366004612f1d565b611b4e565b81801561037b57600080fd5b5061016d61038a366004613362565b611cbb565b81801561039b57600080fd5b5061016d6103aa3660046133c7565b611e40565b8180156103bb57600080fd5b5061016d6103ca366004613418565b611f6b565b8180156103db57600080fd5b5061016d6103ea366004613499565b612179565b8180156103fb57600080fd5b5061016d61040a3660046134db565b612307565b81801561041b57600080fd5b5061016d61042a366004613567565b6124ca565b81801561043b57600080fd5b5061016d61044a3660046135a8565b612606565b81801561045b57600080fd5b5061016d61046a366004612f1d565b6129f8565b81801561047b57600080fd5b5061016d61048a3660046131eb565b612b6c565b610497612dff565b80516104a4906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516104d09160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516105059160019088612cee565b6060810151610515906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516105449160009087612d4b565b6020810151610554906002612c89565b61058d60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6105c660016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e46105de88612df3565b836040518363ffffffff1660e01b81526004016105fc929190613cf6565b600060405180830381600087803b15801561061657600080fd5b505af115801561062a573d6000803e3d6000fd5b5050505050505050505050565b61063f612dff565b805161064c906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516106789160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516106a39160019087612cee565b60408101516106b3906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516106df9160009086612da0565b60208101516106ef906001612c89565b61072c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e461074487612df3565b836040518363ffffffff1660e01b8152600401610762929190613d4b565b600060405180830381600087803b15801561077c57600080fd5b505af1158015610790573d6000803e3d6000fd5b50505050505050505050565b6107a4612dff565b60808101516107b4906002612c89565b60408051808201909152600a815269616374696f6e5479706560b01b602082015260808201516107e79160009089612da0565b60408051808201909152600881526774726164654b657960c01b602082015260808201516108189160019088612da0565b8051610825906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516108519160009087612cee565b6040810151610861906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b6020820152845191830151610894929091600091612da0565b6108d36001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b60208201528482015191830151610907929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b602082015260608501519183015161093a929091600391612da0565b602081015161094a906008612c89565b61099160006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b6109d960016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b610a1d60026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b610a6260036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b610aad600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b610afc6005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b610b4560066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b610b8b6007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4610ba386612df3565b836040518363ffffffff1660e01b81526004016105fc929190613d96565b610bc9612dff565b8051610bd6906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610c029160009088612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610c2d9160019087612cee565b6040810151610c3d906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610c699160009086612da0565b6020810151610c79906001612c89565b610cb66000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e4610cce87612df3565b836040518363ffffffff1660e01b8152600401610762929190613ddc565b610cf4612dff565b8051610d01906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610d2d916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610d589160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151610d859160029088612cee565b6020810151610d95906003612c89565b610dce60006040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b610e0b6001604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b610e4c60026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6487612df3565b836040518363ffffffff1660e01b8152600401610e82929190613e1d565b600060405180830381600087803b158015610e9c57600080fd5b505af1158015610eb0573d6000803e3d6000fd5b505050505050505050505050565b610ec6612dff565b8051610ed3906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151610eff9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151610f349160019088612cee565b6060810151610f44906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151610f739160009087612d4b565b6040810151610f83906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151610faf9160009086612da0565b6020810151610fbf906001612c89565b610ffc6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461101488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613e64565b61103a612dff565b8051611047906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516110739160009086612cee565b6020810151611083906001612c89565b6110cd600060405180604001604052806016815260200175199d5b991a5b99d19858dd1bdc94195c94d958dbdb9960521b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e46110e585612df3565b836040518363ffffffff1660e01b8152600401611103929190613ea7565b600060405180830381600087803b15801561111d57600080fd5b505af1158015611131573d6000803e3d6000fd5b5050505050505050565b611143612dff565b8051611150906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161117c9160009087612cee565b604081015161118c906002612c89565b604080518082018252600581526464656c746160d81b6020820152908201516111b89160009086612da0565b60408051808201825260098152686e65787456616c756560b81b6020820152908201516111e89160019085612da0565b846001600160a01b03166324de01e461120086612df3565b836040518363ffffffff1660e01b815260040161121e929190613ede565b600060405180830381600087803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b505050505050505050565b61125f612dff565b805161126c906001612c89565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516112999160009086612cee565b60208101516112a9906001612c89565b6112e860006040518060400160405280600b81526020016a3ab4a332b2a330b1ba37b960a91b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461130085612df3565b836040518363ffffffff1660e01b8152600401611103929190613f2b565b611326612dff565b8051611333906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161135f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b602082015281516113949160019088612cee565b60608101516113a4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b602082015260608201516113d39160009087612d4b565b60408101516113e3906001612c89565b604080518082018252600581526464656c746160d81b60208201529082015161140f9160009086612da0565b602081015161141f906001612c89565b61145c6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e461147488612df3565b836040518363ffffffff1660e01b81526004016105fc929190613f6d565b61149a612dff565b80516114a7906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516114d3916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516114fe9160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161152b9160029087612cee565b602081015161153b906003612c89565b61157660006040518060400160405280600781526020016674696d654b657960c81b815250878460200151612da0909392919063ffffffff16565b6115af60016040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6115ec6002604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e4610e6486612df3565b61160c612dff565b8051611619906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516116459160009087612cee565b6040810151611655906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516116819160009086612da0565b6020810151611691906001612c89565b6116ce6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e46116e686612df3565b836040518363ffffffff1660e01b815260040161121e929190613fb1565b61170c612dff565b8051611719906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611745916000908a612cee565b6040805180820190915260058152643a37b5b2b760d91b602082015281516117709160019089612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161179d9160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516117cb9160039087612cee565b60208101516117db906002612c89565b611815600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61185660016040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b876001600160a01b03166324de01e461186e87612df3565b836040518363ffffffff1660e01b8152600401610e8292919061400a565b611894612dff565b80516118a1906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516118cd9160009086612cee565b60208101516118dd906001612c89565b611929600060405180604001604052806018815260200177189bdc9c9bddda5b99d19858dd1bdc94195c94d958dbdb9960421b815250848460200151612da0909392919063ffffffff16565b836001600160a01b03166324de01e461194185612df3565b836040518363ffffffff1660e01b815260040161110392919061404c565b611967612dff565b8051611974906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516119a09160009087612cee565b60408101516119b0906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516119dc9160009086612da0565b60208101516119ec906001612c89565b611a296000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611a4186612df3565b836040518363ffffffff1660e01b815260040161121e929190614085565b611a67612dff565b8051611a74906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611aa09160009087612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151611ace9160019086612cee565b6020810151611ade906001612c89565b611b18600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4611b3086612df3565b836040518363ffffffff1660e01b815260040161121e9291906140d2565b611b56612dff565b8051611b63906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611b8f9160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151611bc49160019088612cee565b6060810151611bd4906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151611c039160009087612d4b565b6020810151611c13906002612c89565b611c4c60006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b611c8560016040518060400160405280600581526020016476616c756560d81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611c9d88612df3565b836040518363ffffffff1660e01b81526004016105fc92919061411e565b611cc3612dff565b8051611cd0906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611cfc9160009089612cee565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b60208201528151611d309160019088612cee565b6020810151611d40906003612c89565b611d8360006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b815250868460200151612da0909392919063ffffffff16565b611dc760016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b815250858460200151612da0909392919063ffffffff16565b611e0a60026040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4611e2288612df3565b836040518363ffffffff1660e01b81526004016105fc929190614178565b611e48612dff565b8051611e55906001612c89565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611e809160009088612cee565b6080810151611e90906001612c89565b60408051808201909152600e81526d1d9a5c9d1d585b151bdad95b925960921b60208201526080820151611ec79160009087612da0565b6040810151611ed7906002612c89565b604080518082018252600581526464656c746160d81b602082015290820151611f039160009086612da0565b60408051808201825260098152686e65787456616c756560b81b602082015290820151611f339160019085612da0565b856001600160a01b03166363d16363611f4b87612df3565b86846040518463ffffffff1660e01b8152600401610762939291906141c1565b611f73612dff565b8051611f80906003612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611fac916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611fd7916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516120049160029088612cee565b6020810151612014906004612c89565b61204f60006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b61208860016040518060400160405280600581526020016464656c746160d81b815250868460200151612da0909392919063ffffffff16565b6120c56002604051806040016040528060098152602001686e65787456616c756560b81b815250858460200151612da0909392919063ffffffff16565b61210660036040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e461211e87612df3565b836040518363ffffffff1660e01b815260040161213c929190614214565b600060405180830381600087803b15801561215657600080fd5b505af115801561216a573d6000803e3d6000fd5b50505050505050505050505050565b612181612dff565b805161218e906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516121ba9160009089612cee565b60608101516121ca906001612c89565b60408051808201909152600b81526a34b9a637b733aa37b5b2b760a91b602082015260608201516121fe9160009088612d4b565b608081015161220e906001612c89565b60408051808201909152600f81526e1d9a5c9d1d585b13585c9ad95d1259608a1b602082015260808201516122469160009087612da0565b6040810151612256906001612c89565b604080518082018252600581526464656c746160d81b6020820152908201516122829160009086612da0565b6020810151612292906001612c89565b6122cf6000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166363d163636122e788612df3565b86846040518463ffffffff1660e01b81526004016105fc9392919061425e565b61230f612dff565b805161231c906004612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612348916000908b612cee565b6040805180820190915260058152643a37b5b2b760d91b60208201528151612373916001908a612cee565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516123a09160029088612cee565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516123ce9160039087612cee565b60208101516123de906003612c89565b61241960006040518060400160405280600781526020016674696d654b657960c81b815250888460200151612da0909392919063ffffffff16565b612453600160405180604001604052806006815260200165185b5bdd5b9d60d21b815250858460200151612da0909392919063ffffffff16565b61249460026040518060400160405280600d81526020016c6e657874506f6f6c56616c756560981b815250848460200151612da0909392919063ffffffff16565b886001600160a01b03166324de01e46124ac87612df3565b836040518363ffffffff1660e01b815260040161213c9291906142af565b6124d2612dff565b80516124df906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b6020820152815161250b9160009088612cee565b606081015161251b906001612c89565b60408051808201909152600681526569734c6f6e6760d01b6020820152606082015161254a9160009087612d4b565b602081015161255a906002612c89565b61259360006040518060400160405280600581526020016464656c746160d81b815250858460200151612da0909392919063ffffffff16565b6125d06001604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46125e887612df3565b836040518363ffffffff1660e01b81526004016107629291906142f0565b61260e612dff565b608081015161261e906001612c89565b60408051808201909152600881526774726164654b657960c01b6020820152608082015161264f9160009088612da0565b805161265c906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126889160009087612cee565b6040810151612698906004612c89565b6040805180820182526009815268706f6f6c56616c756560b81b60208201528451918301516126cb929091600091612da0565b61270a6001604051806040016040528060078152602001661b1bdb99d41b9b60ca1b81525085602001518460400151612da0909392919063ffffffff16565b60408051808201825260088152671cda1bdc9d141b9b60c21b6020820152848201519183015161273e929091600291612da0565b60408051808201825260068152651b995d141b9b60d21b6020820152606085015191830151612771929091600391612da0565b6020810151612781906008612c89565b6127c860006040518060400160405280600f81526020016e1b1bdb99d51bdad95b905b5bdd5b9d608a1b81525085608001518460200151612da0909392919063ffffffff16565b61281060016040518060400160405280601081526020016f1cda1bdc9d151bdad95b905b5bdd5b9d60821b8152508560a001518460200151612da0909392919063ffffffff16565b61285460026040518060400160405280600c81526020016b1b1bdb99d51bdad95b955cd960a21b8152508560c001518460200151612da0909392919063ffffffff16565b61289960036040518060400160405280600d81526020016c1cda1bdc9d151bdad95b955cd9609a1b8152508560e001518460200151612da0909392919063ffffffff16565b6128e4600460405180604001604052806012815260200171746f74616c426f72726f77696e674665657360701b8152508561010001518460200151612da0909392919063ffffffff16565b6129336005604051806040016040528060168152602001753137b93937bbb4b733a332b2a837b7b62330b1ba37b960511b8152508561012001518460200151612da0909392919063ffffffff16565b61297c60066040518060400160405280601081526020016f1a5b5c1858dd141bdbdb105b5bdd5b9d60821b8152508561014001518460200151612da0909392919063ffffffff16565b6129c26007604051806040016040528060128152602001716d61726b6574546f6b656e73537570706c7960701b815250848460200151612da0909392919063ffffffff16565b856001600160a01b03166324de01e46129da86612df3565b836040518363ffffffff1660e01b815260040161076292919061433d565b612a00612dff565b8051612a0d906002612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612a399160009089612cee565b60408051808201909152600f81526e31b7b63630ba32b930b62a37b5b2b760891b60208201528151612a6e9160019088612cee565b6060810151612a7e906001612c89565b60408051808201909152600681526569734c6f6e6760d01b60208201526060820151612aad9160009087612d4b565b6040810151612abd906001612c89565b604080518082018252600581526464656c746160d81b602082015290820151612ae99160009086612da0565b6020810151612af9906001612c89565b612b366000604051806040016040528060098152602001686e65787456616c756560b81b815250848460200151612da0909392919063ffffffff16565b866001600160a01b03166324de01e4612b4e88612df3565b836040518363ffffffff1660e01b81526004016105fc929190614380565b612b74612dff565b8051612b81906001612c89565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151612bad9160009087612cee565b6020810151612bbd906002612c89565b612c03600060405180604001604052806012815260200171191a5cdd1c9a589d5d1a5bdb905b5bdd5b9d60721b815250858460200151612da0909392919063ffffffff16565b612c5360016040518060400160405280601c81526020017b1b995e1d141bdcda5d1a5bdb925b5c1858dd141bdbdb105b5bdd5b9d60221b815250848460200151612da0909392919063ffffffff16565b846001600160a01b03166324de01e4612c6b86612df3565b836040518363ffffffff1660e01b815260040161121e9291906143cb565b806001600160401b03811115612ca157612ca1612fe4565b604051908082528060200260200182016040528015612ce757816020015b604080518082019091526060815260006020820152815260200190600190039081612cbf5790505b5090915250565b8184600001518481518110612d0557612d05614418565b6020026020010151600001819052508084600001518481518110612d2b57612d2b614418565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110612d6257612d62614418565b6020026020010151600001819052508084600001518481518110612d8857612d88614418565b60209081029190910181015191151591015250505050565b8184600001518481518110612db757612db7614418565b6020026020010151600001819052508084600001518481518110612ddd57612ddd614418565b6020026020010151602001818152505050505050565b6001600160a01b031690565b604080516101208101909152606060e0820181815261010083019190915281908152602001612e41604051806040016040528060608152602001606081525090565b8152602001612e63604051806040016040528060608152602001606081525090565b8152602001612e85604051806040016040528060608152602001606081525090565b8152602001612ea7604051806040016040528060608152602001606081525090565b8152602001612ec9604051806040016040528060608152602001606081525090565b8152602001612eeb604051806040016040528060608152602001606081525090565b905290565b6001600160a01b0381168114612f0557600080fd5b50565b80358015158114612f1857600080fd5b919050565b60008060008060008060c08789031215612f3657600080fd5b8635612f4181612ef0565b95506020870135612f5181612ef0565b94506040870135612f6181612ef0565b9350612f6f60608801612f08565b9598949750929560808101359460a0909101359350915050565b600080600080600060a08688031215612fa157600080fd5b8535612fac81612ef0565b94506020860135612fbc81612ef0565b93506040860135612fcc81612ef0565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b038111828210171561302b57634e487b7160e01b600052604160045260246000fd5b60405290565b6000610180828403121561304457600080fd5b61304c612ffa565b823581526020808401359082015260408084013590820152606080840135908201526080808401359082015260a0808401359082015260c0808401359082015260e08084013590820152610100808401359082015261012080840135908201526101408084013590820152610160928301359281019290925250919050565b60008060008060008061022087890312156130e557600080fd5b86356130f081612ef0565b95506020870135945060408701359350606087013561310e81612ef0565b925061311d8860808901613031565b9598949750929591949361020090920135925050565b600080600080600080600060e0888a03121561314e57600080fd5b873561315981612ef0565b9650602088013561316981612ef0565b9550604088013561317981612ef0565b9450606088013561318981612ef0565b9699959850939660808101359560a0820135955060c0909101359350915050565b6000806000606084860312156131bf57600080fd5b83356131ca81612ef0565b925060208401356131da81612ef0565b929592945050506040919091013590565b6000806000806080858703121561320157600080fd5b843561320c81612ef0565b9350602085013561321c81612ef0565b93969395505050506040820135916060013590565b600080600080600080600060e0888a03121561324c57600080fd5b873561325781612ef0565b9650602088013561326781612ef0565b9550604088013561327781612ef0565b945060608801359350608088013561328e81612ef0565b9699959850939692959460a0840135945060c09093013592915050565b600080600080600080600060e0888a0312156132c657600080fd5b87356132d181612ef0565b965060208801356132e181612ef0565b955060408801356132f181612ef0565b9450606088013561330181612ef0565b9350608088013561328e81612ef0565b6000806000806080858703121561332757600080fd5b843561333281612ef0565b9350602085013561334281612ef0565b9250604085013561335281612ef0565b9396929550929360600135925050565b60008060008060008060c0878903121561337b57600080fd5b863561338681612ef0565b9550602087013561339681612ef0565b945060408701356133a681612ef0565b959894975094956060810135955060808101359460a0909101359350915050565b600080600080600060a086880312156133df57600080fd5b85356133ea81612ef0565b945060208601356133fa81612ef0565b94979496505050506040830135926060810135926080909101359150565b600080600080600080600080610100898b03121561343557600080fd5b883561344081612ef0565b9750602089013561345081612ef0565b9650604089013561346081612ef0565b955060608901359450608089013561347781612ef0565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60008060008060008060c087890312156134b257600080fd5b86356134bd81612ef0565b955060208701356134cd81612ef0565b94506133a660408801612f08565b600080600080600080600080610100898b0312156134f857600080fd5b883561350381612ef0565b9750602089013561351381612ef0565b9650604089013561352381612ef0565b955060608901359450608089013561353a81612ef0565b935060a089013561354a81612ef0565b979a969950949793969295929450505060c08201359160e0013590565b600080600080600060a0868803121561357f57600080fd5b853561358a81612ef0565b9450602086013561359a81612ef0565b9350612fcc60408701612f08565b600080600080600061020086880312156135c157600080fd5b85356135cc81612ef0565b94506020860135935060408601356135e381612ef0565b92506135f28760608801613031565b949793965091946101e0013592915050565b6000815180845260005b8181101561362a5760208185018101518683018201520161360e565b506000602082860101526020601f19601f83011685010191505092915050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261368e6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156136d85783516001600160a01b0316825260209384019360019390930192909101906136ad565b5060209a8b019a90955093909301925050600101613668565b50909695505050505050565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561377757605f19888603018352835180516040875261374f6040880182613604565b6020928301516001600160a01b03169783019790975250938401939290920191600101613729565b5050505060208301518482036020860152613792828261364a565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f1985840301885281518051604085526137df6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b8083101561382157835182526020820191506020840193506001830192506137fe565b5060209a8b019a909550939093019250506001016137b9565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f19888603018352835180516040875261388c6040880182613604565b6020928301519783019790975250938401939290920191600101613866565b5050505060208301518482036020860152613792828261379b565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156138ab57605f1988860301835283518051604087526139186040880182613604565b60209283015197830197909752509384019392909201916001016138f2565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f19858403018852815180516040855261397b6040860182613604565b6020928301518682038785015280518083529084019360009350909101905b808310156139bf5783511515825260208201915060208401935060018301925061399a565b5060209a8b019a90955093909301925050600101613955565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613a4b57605f198886030183528351805160408752613a2a6040880182613604565b60209283015115159783019790975250938401939290920191600101613a04565b50505050602083015184820360208601526137928282613937565b600082825180855260208501945060208160051b8301016020850160005b838110156136f157601f198584030188528151805160408552613aaa6040860182613604565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b82811015613b0357601f19858303018452613aee828751613604565b60209687019694909401939150600101613ad2565b508097505050505050602082019150602088019750600181019050613a84565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613b756040880182613604565b9050602082015191508681036020880152613b908183613604565b965050506020938401939290920191600101613b4f565b50505050602083015184820360208601526137928282613a66565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015613ba757605f198886030183528351805160408752613c146040880182613604565b9050602082015191508681036020880152613c2f8183613604565b965050506020938401939290920191600101613bee565b6000815160e08452613c5b60e08501826136fd565b905060208301518482036020860152613c74828261383a565b91505060408301518482036040860152613c8e82826138c6565b91505060608301518482036060860152613ca882826139d8565b91505060808301518482036080860152613cc282826138c6565b91505060a083015184820360a0860152613cdc8282613b23565b91505060c083015184820360c08601526137928282613bc2565b60608152601e60608201527f46756e64696e67466565416d6f756e7450657253697a65557064617465640000608082015282602082015260a060408201526000613d4360a0830184613c46565b949350505050565b60608152601b60608201527a14ddd85c125b5c1858dd141bdbdb105b5bdd5b9d155c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601660608201527513585c9ad95d141bdbdb15985b1d59555c19185d195960521b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526011606082015270141bdbdb105b5bdd5b9d155c19185d1959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601760608201527610db185a5b58589b19519d5b991a5b99d55c19185d1959604a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601360608201527213dc195b925b9d195c995cdd155c19185d1959606a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152600760608201526646756e64696e6760c81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f546f74616c50656e64696e67496d70616374416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526012606082015271155a519959519858dd1bdc955c19185d195960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601460608201527310dbdb1b185d195c985b14dd5b555c19185d195960621b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602360608201527f4c656e74506f736974696f6e496d70616374506f6f6c416d6f756e74557064616080820152621d195960ea1b60a082015282602082015260c060408201526000613d4360c0830184613c46565b606081526012606082015271119d5b991a5b99d199595cd0db185a5b595960721b608082015282602082015260a060408201526000613d4360a0830184613c46565b606081526009606082015268426f72726f77696e6760b81b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601f60608201527f506f736974696f6e496d70616374506f6f6c416d6f756e745570646174656400608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601c60608201527b141bdcda5d1a5bdb925b5c1858dd141bdbdb15da5d1a191c985dd85b60221b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602460608201527f436c61696d61626c6546756e64696e67416d6f756e7450657253697a65557064608082015263185d195960e21b60a082015282602082015260c060408201526000613d4360c0830184613c46565b6060815260196060820152782632b73a24b6b830b1ba20b6b7bab73a2932b23ab1ba34b7b760391b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601f60808201527f5669727475616c506f736974696f6e496e76656e746f7279557064617465640060a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601a60608201527910db185a5b58589b1950dbdb1b185d195c985b155c19185d195960321b608082015282602082015260a060408201526000613d4360a0830184613c46565b60808152601b60808201527a159a5c9d1d585b14ddd85c125b9d995b9d1bdc9e555c19185d1959602a1b60a082015283602082015282604082015260c06060820152600061379260c0830184613c46565b60608152601160608201527010dbdb1b185d195c985b10db185a5b5959607a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152602060608201527f43756d756c6174697665426f72726f77696e67466163746f7255706461746564608082015282602082015260a060408201526000613d4360a0830184613c46565b6060815260136060820152724d61726b6574506f6f6c56616c7565496e666f60681b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601b60608201527a13dc195b925b9d195c995cdd125b951bdad95b9cd55c19185d1959602a1b608082015282602082015260a060408201526000613d4360a0830184613c46565b60608152601d60608201527f506f736974696f6e496d70616374506f6f6c4469737472696275746564000000608082015282602082015260a060408201526000613d4360a0830184613c46565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220d11068c55b5896d32d6994095243826d6b989a41cc34fe6ac3818f26df692dd564736f6c634300081d0033", "libraries": {}, "devdoc": { "kind": "dev", diff --git a/deployments/arbitrum/MarketStoreUtils.json b/deployments/arbitrum/MarketStoreUtils.json index 916c48e03..8c8c08623 100644 --- a/deployments/arbitrum/MarketStoreUtils.json +++ b/deployments/arbitrum/MarketStoreUtils.json @@ -1,5 +1,5 @@ { - "address": "0xd727120ac811e9136D4a5D5C6219aEE37e275785", + "address": "0x2e5D10A48C00cFcc6A31af873118d739323Ff71B", "abi": [ { "inputs": [ @@ -183,28 +183,28 @@ "type": "function" } ], - "transactionHash": "0x8c0dcf0963136ce4cacc6a04305f62ff56798bb4a9efa033e87cc3ab1b8a8f2d", + "transactionHash": "0xdd393a6755599dc7e8fb5b3eb983102c743cfd31efc4c3b292f6e6312b3df737", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0xd727120ac811e9136D4a5D5C6219aEE37e275785", - "transactionIndex": 6, - "gasUsed": "1106583", + "contractAddress": "0x2e5D10A48C00cFcc6A31af873118d739323Ff71B", + "transactionIndex": 2, + "gasUsed": "1098052", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1bc52f21ec2195ed46aa6f8c85b152316ffd3a4b06ad6a65023c228442a73697", - "transactionHash": "0x8c0dcf0963136ce4cacc6a04305f62ff56798bb4a9efa033e87cc3ab1b8a8f2d", + "blockHash": "0x4209d5a2bbe1f31282919dabf9c76bf7c168351b97f8282670cfc7c116b2b09d", + "transactionHash": "0xdd393a6755599dc7e8fb5b3eb983102c743cfd31efc4c3b292f6e6312b3df737", "logs": [], - "blockNumber": 367562388, - "cumulativeGasUsed": "1551278", + "blockNumber": 390053883, + "cumulativeGasUsed": "1178204", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 22, - "solcInputHash": "79ca35a0eb57a5a4e0af2a0fc5a1dbeb", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"key\",\"type\":\"address\"}],\"name\":\"MarketNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INDEX_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LONG_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET_SALT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SHORT_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"key\",\"type\":\"address\"}],\"name\":\"get\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"getBySalt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Library for market storage functions\",\"kind\":\"dev\",\"methods\":{},\"title\":\"MarketStoreUtils\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/MarketStoreUtils.sol\":\"MarketStoreUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"}},\"version\":1}", - "bytecode": "0x6112b0610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100975760003560e01c8062a28b361461009c5780633f0dd9a6146100b7578063492dec5a146100d95780635231e24f146100e1578063537803c2146100e95780637785f6601461013f57806391bf0ff21461015f578063a8d8fff514610167578063c11201f71461017a578063db73bb1514610182575b600080fd5b6100a461018a565b6040519081526020015b60405180910390f35b8180156100c357600080fd5b506100d76100d2366004610fb3565b6101b2565b005b6100a4610612565b6100a4610640565b6100fc6100f7366004610ff4565b61064f565b6040516100ae919081516001600160a01b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b81801561014b57600080fd5b506100d761015a366004611020565b6106e6565b6100a4610af3565b6100fc6101753660046110ed565b610b02565b6100a4610ef4565b6100a4610f03565b60405160200161019990611126565b6040516020818303038152906040528051906020012081565b826001600160a01b031663c769d1a16040516020016101d09061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b815260040161020492919061116f565b602060405180830381865afa158015610221573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102459190611186565b61027157604051636918f9bf60e01b81526001600160a01b038316600482015260240160405180910390fd5b826001600160a01b03166369721d4160405160200161028f9061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b81526004016102c392919061116f565b600060405180830381600087803b1580156102dd57600080fd5b505af11580156102f1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb683604051602001610314906111af565b6040516020818303038152906040528051906020012060405160200161033b9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161036f91815260200190565b600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb6836040516020016103c0906111ee565b604051602081830303815290604052805190602001206040516020016103e79291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161041b91815260200190565b600060405180830381600087803b15801561043557600080fd5b505af1158015610449573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161046c90611126565b604051602081830303815290604052805190602001206040516020016104939291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016104c791815260200190565b600060405180830381600087803b1580156104e157600080fd5b505af11580156104f5573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161051890611213565b6040516020818303038152906040528051906020012060405160200161053f9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161057391815260200190565b600060405180830381600087803b15801561058d57600080fd5b505af11580156105a1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb66105bd83610f12565b6040518263ffffffff1660e01b81526004016105db91815260200190565b600060405180830381600087803b1580156105f557600080fd5b505af1158015610609573d6000803e3d6000fd5b50505050505050565b604051602001610199906020808252600a90820152694d41524b45545f4b455960b01b604082015260600190565b60405160200161019990611213565b610657610f64565b6000836001600160a01b03166321f8a72161067185610f12565b6040518263ffffffff1660e01b815260040161068f91815260200190565b602060405180830381865afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d09190611238565b90506106dc8482610b02565b9150505b92915050565b836001600160a01b031663b348e6396040516020016107049061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b815260040161073892919061116f565b600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b50505050836001600160a01b031663ca446dd961078284610f12565b856040518363ffffffff1660e01b81526004016107a092919061116f565b6020604051808303816000875af11580156107bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e39190611238565b50836001600160a01b031663ca446dd984604051602001610803906111af565b6040516020818303038152906040528051906020012060405160200161082a9291906111d5565b60408051601f1981840301815290829052805160209091012084516001600160e01b031960e085901b1683526108629260040161116f565b6020604051808303816000875af1158015610881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190611238565b50836001600160a01b031663ca446dd9846040516020016108c5906111ee565b604051602081830303815290604052805190602001206040516020016108ec9291906111d5565b6040516020818303038152906040528051906020012083602001516040518363ffffffff1660e01b815260040161092492919061116f565b6020604051808303816000875af1158015610943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109679190611238565b50836001600160a01b031663ca446dd98460405160200161098790611126565b604051602081830303815290604052805190602001206040516020016109ae9291906111d5565b60408051601f198184030181528282528051602090910120908501516001600160e01b031960e085901b1683526109e79260040161116f565b6020604051808303816000875af1158015610a06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2a9190611238565b50836001600160a01b031663ca446dd984604051602001610a4a90611213565b60405160208183030381529060405280519060200120604051602001610a719291906111d5565b6040516020818303038152906040528051906020012083606001516040518363ffffffff1660e01b8152600401610aa992919061116f565b6020604051808303816000875af1158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190611238565b5050505050565b604051602001610199906111af565b610b0a610f64565b610b12610f64565b836001600160a01b031663c769d1a1604051602001610b309061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b8152600401610b6492919061116f565b602060405180830381865afa158015610b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba59190611186565b610bb05790506106e0565b836001600160a01b03166321f8a72184604051602001610bcf906111af565b60405160208183030381529060405280519060200120604051602001610bf69291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610c2a91815260200190565b602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190611238565b6001600160a01b039081168252604051908516906321f8a721908590610c93906020016111ee565b60405160208183030381529060405280519060200120604051602001610cba9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610cee91815260200190565b602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190611238565b81602001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610d6b90611126565b60405160208183030381529060405280519060200120604051602001610d929291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dc691815260200190565b602060405180830381865afa158015610de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e079190611238565b81604001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610e4390611213565b60405160208183030381529060405280519060200120604051602001610e6a9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610e9e91815260200190565b602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf9190611238565b6001600160a01b031660608201529392505050565b604051602001610199906111ee565b60405160200161019990611255565b6000604051602001610f2390611255565b60408051601f198184030181528282528051602091820120908301528101839052606001604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6001600160a01b0381168114610fa057600080fd5b50565b8035610fae81610f8b565b919050565b600080600060608486031215610fc857600080fd5b8335610fd381610f8b565b92506020840135610fe381610f8b565b929592945050506040919091013590565b6000806040838503121561100757600080fd5b823561101281610f8b565b946020939093013593505050565b60008060008084860360e081121561103757600080fd5b853561104281610f8b565b9450602086013561105281610f8b565b9350604086013592506080605f198201121561106d57600080fd5b50604051608081016001600160401b038111828210171561109e57634e487b7160e01b600052604160045260246000fd5b6040526110ad60608701610fa3565b81526110bb60808701610fa3565b60208201526110cc60a08701610fa3565b60408201526110dd60c08701610fa3565b6060820152939692955090935050565b6000806040838503121561110057600080fd5b823561110b81610f8b565b9150602083013561111b81610f8b565b809150509250929050565b6020808252600a90820152692627a723afaa27a5a2a760b11b604082015260600190565b6020808252600b908201526a13505492d15517d31254d560aa1b604082015260600190565b9182526001600160a01b0316602082015260400190565b60006020828403121561119857600080fd5b815180151581146111a857600080fd5b9392505050565b6020808252600c908201526b26a0a925a2aa2faa27a5a2a760a11b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6020808252600b908201526a24a72222ac2faa27a5a2a760a91b604082015260600190565b6020808252600b908201526a29a427a92a2faa27a5a2a760a91b604082015260600190565b60006020828403121561124a57600080fd5b81516111a881610f8b565b6020808252600b908201526a13505492d15517d4d0531560aa1b60408201526060019056fea2646970667358221220c6f11bcf13d41ba820d76d28b911d40c208cb9d9cef891ea435433c153ff6a5064736f6c634300081d0033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100975760003560e01c8062a28b361461009c5780633f0dd9a6146100b7578063492dec5a146100d95780635231e24f146100e1578063537803c2146100e95780637785f6601461013f57806391bf0ff21461015f578063a8d8fff514610167578063c11201f71461017a578063db73bb1514610182575b600080fd5b6100a461018a565b6040519081526020015b60405180910390f35b8180156100c357600080fd5b506100d76100d2366004610fb3565b6101b2565b005b6100a4610612565b6100a4610640565b6100fc6100f7366004610ff4565b61064f565b6040516100ae919081516001600160a01b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b81801561014b57600080fd5b506100d761015a366004611020565b6106e6565b6100a4610af3565b6100fc6101753660046110ed565b610b02565b6100a4610ef4565b6100a4610f03565b60405160200161019990611126565b6040516020818303038152906040528051906020012081565b826001600160a01b031663c769d1a16040516020016101d09061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b815260040161020492919061116f565b602060405180830381865afa158015610221573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102459190611186565b61027157604051636918f9bf60e01b81526001600160a01b038316600482015260240160405180910390fd5b826001600160a01b03166369721d4160405160200161028f9061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b81526004016102c392919061116f565b600060405180830381600087803b1580156102dd57600080fd5b505af11580156102f1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb683604051602001610314906111af565b6040516020818303038152906040528051906020012060405160200161033b9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161036f91815260200190565b600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb6836040516020016103c0906111ee565b604051602081830303815290604052805190602001206040516020016103e79291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161041b91815260200190565b600060405180830381600087803b15801561043557600080fd5b505af1158015610449573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161046c90611126565b604051602081830303815290604052805190602001206040516020016104939291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016104c791815260200190565b600060405180830381600087803b1580156104e157600080fd5b505af11580156104f5573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161051890611213565b6040516020818303038152906040528051906020012060405160200161053f9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161057391815260200190565b600060405180830381600087803b15801561058d57600080fd5b505af11580156105a1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb66105bd83610f12565b6040518263ffffffff1660e01b81526004016105db91815260200190565b600060405180830381600087803b1580156105f557600080fd5b505af1158015610609573d6000803e3d6000fd5b50505050505050565b604051602001610199906020808252600a90820152694d41524b45545f4b455960b01b604082015260600190565b60405160200161019990611213565b610657610f64565b6000836001600160a01b03166321f8a72161067185610f12565b6040518263ffffffff1660e01b815260040161068f91815260200190565b602060405180830381865afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d09190611238565b90506106dc8482610b02565b9150505b92915050565b836001600160a01b031663b348e6396040516020016107049061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b815260040161073892919061116f565b600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b50505050836001600160a01b031663ca446dd961078284610f12565b856040518363ffffffff1660e01b81526004016107a092919061116f565b6020604051808303816000875af11580156107bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e39190611238565b50836001600160a01b031663ca446dd984604051602001610803906111af565b6040516020818303038152906040528051906020012060405160200161082a9291906111d5565b60408051601f1981840301815290829052805160209091012084516001600160e01b031960e085901b1683526108629260040161116f565b6020604051808303816000875af1158015610881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190611238565b50836001600160a01b031663ca446dd9846040516020016108c5906111ee565b604051602081830303815290604052805190602001206040516020016108ec9291906111d5565b6040516020818303038152906040528051906020012083602001516040518363ffffffff1660e01b815260040161092492919061116f565b6020604051808303816000875af1158015610943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109679190611238565b50836001600160a01b031663ca446dd98460405160200161098790611126565b604051602081830303815290604052805190602001206040516020016109ae9291906111d5565b60408051601f198184030181528282528051602090910120908501516001600160e01b031960e085901b1683526109e79260040161116f565b6020604051808303816000875af1158015610a06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2a9190611238565b50836001600160a01b031663ca446dd984604051602001610a4a90611213565b60405160208183030381529060405280519060200120604051602001610a719291906111d5565b6040516020818303038152906040528051906020012083606001516040518363ffffffff1660e01b8152600401610aa992919061116f565b6020604051808303816000875af1158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190611238565b5050505050565b604051602001610199906111af565b610b0a610f64565b610b12610f64565b836001600160a01b031663c769d1a1604051602001610b309061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b8152600401610b6492919061116f565b602060405180830381865afa158015610b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba59190611186565b610bb05790506106e0565b836001600160a01b03166321f8a72184604051602001610bcf906111af565b60405160208183030381529060405280519060200120604051602001610bf69291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610c2a91815260200190565b602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190611238565b6001600160a01b039081168252604051908516906321f8a721908590610c93906020016111ee565b60405160208183030381529060405280519060200120604051602001610cba9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610cee91815260200190565b602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190611238565b81602001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610d6b90611126565b60405160208183030381529060405280519060200120604051602001610d929291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dc691815260200190565b602060405180830381865afa158015610de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e079190611238565b81604001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610e4390611213565b60405160208183030381529060405280519060200120604051602001610e6a9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610e9e91815260200190565b602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf9190611238565b6001600160a01b031660608201529392505050565b604051602001610199906111ee565b60405160200161019990611255565b6000604051602001610f2390611255565b60408051601f198184030181528282528051602091820120908301528101839052606001604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6001600160a01b0381168114610fa057600080fd5b50565b8035610fae81610f8b565b919050565b600080600060608486031215610fc857600080fd5b8335610fd381610f8b565b92506020840135610fe381610f8b565b929592945050506040919091013590565b6000806040838503121561100757600080fd5b823561101281610f8b565b946020939093013593505050565b60008060008084860360e081121561103757600080fd5b853561104281610f8b565b9450602086013561105281610f8b565b9350604086013592506080605f198201121561106d57600080fd5b50604051608081016001600160401b038111828210171561109e57634e487b7160e01b600052604160045260246000fd5b6040526110ad60608701610fa3565b81526110bb60808701610fa3565b60208201526110cc60a08701610fa3565b60408201526110dd60c08701610fa3565b6060820152939692955090935050565b6000806040838503121561110057600080fd5b823561110b81610f8b565b9150602083013561111b81610f8b565b809150509250929050565b6020808252600a90820152692627a723afaa27a5a2a760b11b604082015260600190565b6020808252600b908201526a13505492d15517d31254d560aa1b604082015260600190565b9182526001600160a01b0316602082015260400190565b60006020828403121561119857600080fd5b815180151581146111a857600080fd5b9392505050565b6020808252600c908201526b26a0a925a2aa2faa27a5a2a760a11b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6020808252600b908201526a24a72222ac2faa27a5a2a760a91b604082015260600190565b6020808252600b908201526a29a427a92a2faa27a5a2a760a91b604082015260600190565b60006020828403121561124a57600080fd5b81516111a881610f8b565b6020808252600b908201526a13505492d15517d4d0531560aa1b60408201526060019056fea2646970667358221220c6f11bcf13d41ba820d76d28b911d40c208cb9d9cef891ea435433c153ff6a5064736f6c634300081d0033", + "numDeployments": 23, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"key\",\"type\":\"address\"}],\"name\":\"MarketNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INDEX_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LONG_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET_SALT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SHORT_TOKEN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"key\",\"type\":\"address\"}],\"name\":\"get\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"getBySalt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Library for market storage functions\",\"kind\":\"dev\",\"methods\":{},\"title\":\"MarketStoreUtils\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/MarketStoreUtils.sol\":\"MarketStoreUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x6112b0610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100975760003560e01c8062a28b361461009c5780633f0dd9a6146100b7578063492dec5a146100d95780635231e24f146100e1578063537803c2146100e95780637785f6601461013f57806391bf0ff21461015f578063a8d8fff514610167578063c11201f71461017a578063db73bb1514610182575b600080fd5b6100a461018a565b6040519081526020015b60405180910390f35b8180156100c357600080fd5b506100d76100d2366004610fb3565b6101b2565b005b6100a4610612565b6100a4610640565b6100fc6100f7366004610ff4565b61064f565b6040516100ae919081516001600160a01b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b81801561014b57600080fd5b506100d761015a366004611020565b6106e6565b6100a4610af3565b6100fc6101753660046110ed565b610b02565b6100a4610ef4565b6100a4610f03565b60405160200161019990611126565b6040516020818303038152906040528051906020012081565b826001600160a01b031663c769d1a16040516020016101d09061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b815260040161020492919061116f565b602060405180830381865afa158015610221573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102459190611186565b61027157604051636918f9bf60e01b81526001600160a01b038316600482015260240160405180910390fd5b826001600160a01b03166369721d4160405160200161028f9061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b81526004016102c392919061116f565b600060405180830381600087803b1580156102dd57600080fd5b505af11580156102f1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb683604051602001610314906111af565b6040516020818303038152906040528051906020012060405160200161033b9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161036f91815260200190565b600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb6836040516020016103c0906111ee565b604051602081830303815290604052805190602001206040516020016103e79291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161041b91815260200190565b600060405180830381600087803b15801561043557600080fd5b505af1158015610449573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161046c90611126565b604051602081830303815290604052805190602001206040516020016104939291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016104c791815260200190565b600060405180830381600087803b1580156104e157600080fd5b505af11580156104f5573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161051890611213565b6040516020818303038152906040528051906020012060405160200161053f9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161057391815260200190565b600060405180830381600087803b15801561058d57600080fd5b505af11580156105a1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb66105bd83610f12565b6040518263ffffffff1660e01b81526004016105db91815260200190565b600060405180830381600087803b1580156105f557600080fd5b505af1158015610609573d6000803e3d6000fd5b50505050505050565b604051602001610199906020808252600a90820152694d41524b45545f4b455960b01b604082015260600190565b60405160200161019990611213565b610657610f64565b6000836001600160a01b03166321f8a72161067185610f12565b6040518263ffffffff1660e01b815260040161068f91815260200190565b602060405180830381865afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d09190611238565b90506106dc8482610b02565b9150505b92915050565b836001600160a01b031663b348e6396040516020016107049061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b815260040161073892919061116f565b600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b50505050836001600160a01b031663ca446dd961078284610f12565b856040518363ffffffff1660e01b81526004016107a092919061116f565b6020604051808303816000875af11580156107bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e39190611238565b50836001600160a01b031663ca446dd984604051602001610803906111af565b6040516020818303038152906040528051906020012060405160200161082a9291906111d5565b60408051601f1981840301815290829052805160209091012084516001600160e01b031960e085901b1683526108629260040161116f565b6020604051808303816000875af1158015610881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190611238565b50836001600160a01b031663ca446dd9846040516020016108c5906111ee565b604051602081830303815290604052805190602001206040516020016108ec9291906111d5565b6040516020818303038152906040528051906020012083602001516040518363ffffffff1660e01b815260040161092492919061116f565b6020604051808303816000875af1158015610943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109679190611238565b50836001600160a01b031663ca446dd98460405160200161098790611126565b604051602081830303815290604052805190602001206040516020016109ae9291906111d5565b60408051601f198184030181528282528051602090910120908501516001600160e01b031960e085901b1683526109e79260040161116f565b6020604051808303816000875af1158015610a06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2a9190611238565b50836001600160a01b031663ca446dd984604051602001610a4a90611213565b60405160208183030381529060405280519060200120604051602001610a719291906111d5565b6040516020818303038152906040528051906020012083606001516040518363ffffffff1660e01b8152600401610aa992919061116f565b6020604051808303816000875af1158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190611238565b5050505050565b604051602001610199906111af565b610b0a610f64565b610b12610f64565b836001600160a01b031663c769d1a1604051602001610b309061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b8152600401610b6492919061116f565b602060405180830381865afa158015610b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba59190611186565b610bb05790506106e0565b836001600160a01b03166321f8a72184604051602001610bcf906111af565b60405160208183030381529060405280519060200120604051602001610bf69291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610c2a91815260200190565b602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190611238565b6001600160a01b039081168252604051908516906321f8a721908590610c93906020016111ee565b60405160208183030381529060405280519060200120604051602001610cba9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610cee91815260200190565b602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190611238565b81602001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610d6b90611126565b60405160208183030381529060405280519060200120604051602001610d929291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dc691815260200190565b602060405180830381865afa158015610de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e079190611238565b81604001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610e4390611213565b60405160208183030381529060405280519060200120604051602001610e6a9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610e9e91815260200190565b602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf9190611238565b6001600160a01b031660608201529392505050565b604051602001610199906111ee565b60405160200161019990611255565b6000604051602001610f2390611255565b60408051601f198184030181528282528051602091820120908301528101839052606001604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6001600160a01b0381168114610fa057600080fd5b50565b8035610fae81610f8b565b919050565b600080600060608486031215610fc857600080fd5b8335610fd381610f8b565b92506020840135610fe381610f8b565b929592945050506040919091013590565b6000806040838503121561100757600080fd5b823561101281610f8b565b946020939093013593505050565b60008060008084860360e081121561103757600080fd5b853561104281610f8b565b9450602086013561105281610f8b565b9350604086013592506080605f198201121561106d57600080fd5b50604051608081016001600160401b038111828210171561109e57634e487b7160e01b600052604160045260246000fd5b6040526110ad60608701610fa3565b81526110bb60808701610fa3565b60208201526110cc60a08701610fa3565b60408201526110dd60c08701610fa3565b6060820152939692955090935050565b6000806040838503121561110057600080fd5b823561110b81610f8b565b9150602083013561111b81610f8b565b809150509250929050565b6020808252600a90820152692627a723afaa27a5a2a760b11b604082015260600190565b6020808252600b908201526a13505492d15517d31254d560aa1b604082015260600190565b9182526001600160a01b0316602082015260400190565b60006020828403121561119857600080fd5b815180151581146111a857600080fd5b9392505050565b6020808252600c908201526b26a0a925a2aa2faa27a5a2a760a11b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6020808252600b908201526a24a72222ac2faa27a5a2a760a91b604082015260600190565b6020808252600b908201526a29a427a92a2faa27a5a2a760a91b604082015260600190565b60006020828403121561124a57600080fd5b81516111a881610f8b565b6020808252600b908201526a13505492d15517d4d0531560aa1b60408201526060019056fea26469706673582212209efa428abd8150c9ae47dc2f2d0e41fab13050b29e51fcc0dad02738e215af2f64736f6c634300081d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100975760003560e01c8062a28b361461009c5780633f0dd9a6146100b7578063492dec5a146100d95780635231e24f146100e1578063537803c2146100e95780637785f6601461013f57806391bf0ff21461015f578063a8d8fff514610167578063c11201f71461017a578063db73bb1514610182575b600080fd5b6100a461018a565b6040519081526020015b60405180910390f35b8180156100c357600080fd5b506100d76100d2366004610fb3565b6101b2565b005b6100a4610612565b6100a4610640565b6100fc6100f7366004610ff4565b61064f565b6040516100ae919081516001600160a01b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b81801561014b57600080fd5b506100d761015a366004611020565b6106e6565b6100a4610af3565b6100fc6101753660046110ed565b610b02565b6100a4610ef4565b6100a4610f03565b60405160200161019990611126565b6040516020818303038152906040528051906020012081565b826001600160a01b031663c769d1a16040516020016101d09061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b815260040161020492919061116f565b602060405180830381865afa158015610221573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102459190611186565b61027157604051636918f9bf60e01b81526001600160a01b038316600482015260240160405180910390fd5b826001600160a01b03166369721d4160405160200161028f9061114a565b60405160208183030381529060405280519060200120846040518363ffffffff1660e01b81526004016102c392919061116f565b600060405180830381600087803b1580156102dd57600080fd5b505af11580156102f1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb683604051602001610314906111af565b6040516020818303038152906040528051906020012060405160200161033b9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161036f91815260200190565b600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb6836040516020016103c0906111ee565b604051602081830303815290604052805190602001206040516020016103e79291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161041b91815260200190565b600060405180830381600087803b15801561043557600080fd5b505af1158015610449573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161046c90611126565b604051602081830303815290604052805190602001206040516020016104939291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016104c791815260200190565b600060405180830381600087803b1580156104e157600080fd5b505af11580156104f5573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb68360405160200161051890611213565b6040516020818303038152906040528051906020012060405160200161053f9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161057391815260200190565b600060405180830381600087803b15801561058d57600080fd5b505af11580156105a1573d6000803e3d6000fd5b50505050826001600160a01b0316639faf6fb66105bd83610f12565b6040518263ffffffff1660e01b81526004016105db91815260200190565b600060405180830381600087803b1580156105f557600080fd5b505af1158015610609573d6000803e3d6000fd5b50505050505050565b604051602001610199906020808252600a90820152694d41524b45545f4b455960b01b604082015260600190565b60405160200161019990611213565b610657610f64565b6000836001600160a01b03166321f8a72161067185610f12565b6040518263ffffffff1660e01b815260040161068f91815260200190565b602060405180830381865afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d09190611238565b90506106dc8482610b02565b9150505b92915050565b836001600160a01b031663b348e6396040516020016107049061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b815260040161073892919061116f565b600060405180830381600087803b15801561075257600080fd5b505af1158015610766573d6000803e3d6000fd5b50505050836001600160a01b031663ca446dd961078284610f12565b856040518363ffffffff1660e01b81526004016107a092919061116f565b6020604051808303816000875af11580156107bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e39190611238565b50836001600160a01b031663ca446dd984604051602001610803906111af565b6040516020818303038152906040528051906020012060405160200161082a9291906111d5565b60408051601f1981840301815290829052805160209091012084516001600160e01b031960e085901b1683526108629260040161116f565b6020604051808303816000875af1158015610881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a59190611238565b50836001600160a01b031663ca446dd9846040516020016108c5906111ee565b604051602081830303815290604052805190602001206040516020016108ec9291906111d5565b6040516020818303038152906040528051906020012083602001516040518363ffffffff1660e01b815260040161092492919061116f565b6020604051808303816000875af1158015610943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109679190611238565b50836001600160a01b031663ca446dd98460405160200161098790611126565b604051602081830303815290604052805190602001206040516020016109ae9291906111d5565b60408051601f198184030181528282528051602090910120908501516001600160e01b031960e085901b1683526109e79260040161116f565b6020604051808303816000875af1158015610a06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2a9190611238565b50836001600160a01b031663ca446dd984604051602001610a4a90611213565b60405160208183030381529060405280519060200120604051602001610a719291906111d5565b6040516020818303038152906040528051906020012083606001516040518363ffffffff1660e01b8152600401610aa992919061116f565b6020604051808303816000875af1158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190611238565b5050505050565b604051602001610199906111af565b610b0a610f64565b610b12610f64565b836001600160a01b031663c769d1a1604051602001610b309061114a565b60405160208183030381529060405280519060200120856040518363ffffffff1660e01b8152600401610b6492919061116f565b602060405180830381865afa158015610b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba59190611186565b610bb05790506106e0565b836001600160a01b03166321f8a72184604051602001610bcf906111af565b60405160208183030381529060405280519060200120604051602001610bf69291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610c2a91815260200190565b602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190611238565b6001600160a01b039081168252604051908516906321f8a721908590610c93906020016111ee565b60405160208183030381529060405280519060200120604051602001610cba9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610cee91815260200190565b602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190611238565b81602001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610d6b90611126565b60405160208183030381529060405280519060200120604051602001610d929291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dc691815260200190565b602060405180830381865afa158015610de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e079190611238565b81604001906001600160a01b031690816001600160a01b031681525050836001600160a01b03166321f8a72184604051602001610e4390611213565b60405160208183030381529060405280519060200120604051602001610e6a9291906111d5565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610e9e91815260200190565b602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf9190611238565b6001600160a01b031660608201529392505050565b604051602001610199906111ee565b60405160200161019990611255565b6000604051602001610f2390611255565b60408051601f198184030181528282528051602091820120908301528101839052606001604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6001600160a01b0381168114610fa057600080fd5b50565b8035610fae81610f8b565b919050565b600080600060608486031215610fc857600080fd5b8335610fd381610f8b565b92506020840135610fe381610f8b565b929592945050506040919091013590565b6000806040838503121561100757600080fd5b823561101281610f8b565b946020939093013593505050565b60008060008084860360e081121561103757600080fd5b853561104281610f8b565b9450602086013561105281610f8b565b9350604086013592506080605f198201121561106d57600080fd5b50604051608081016001600160401b038111828210171561109e57634e487b7160e01b600052604160045260246000fd5b6040526110ad60608701610fa3565b81526110bb60808701610fa3565b60208201526110cc60a08701610fa3565b60408201526110dd60c08701610fa3565b6060820152939692955090935050565b6000806040838503121561110057600080fd5b823561110b81610f8b565b9150602083013561111b81610f8b565b809150509250929050565b6020808252600a90820152692627a723afaa27a5a2a760b11b604082015260600190565b6020808252600b908201526a13505492d15517d31254d560aa1b604082015260600190565b9182526001600160a01b0316602082015260400190565b60006020828403121561119857600080fd5b815180151581146111a857600080fd5b9392505050565b6020808252600c908201526b26a0a925a2aa2faa27a5a2a760a11b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6020808252600b908201526a24a72222ac2faa27a5a2a760a91b604082015260600190565b6020808252600b908201526a29a427a92a2faa27a5a2a760a91b604082015260600190565b60006020828403121561124a57600080fd5b81516111a881610f8b565b6020808252600b908201526a13505492d15517d4d0531560aa1b60408201526060019056fea26469706673582212209efa428abd8150c9ae47dc2f2d0e41fab13050b29e51fcc0dad02738e215af2f64736f6c634300081d0033", "libraries": {}, "devdoc": { "details": "Library for market storage functions", diff --git a/deployments/arbitrum/MarketUtils.json b/deployments/arbitrum/MarketUtils.json index cd42c3e7d..5cacef96c 100644 --- a/deployments/arbitrum/MarketUtils.json +++ b/deployments/arbitrum/MarketUtils.json @@ -1,5 +1,5 @@ { - "address": "0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96", + "address": "0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB", "abi": [ { "inputs": [ @@ -810,31 +810,31 @@ "type": "function" } ], - "transactionHash": "0xd73596df9c81efa589d801e805445a1f49479e418e398dde2e7ae105f2f4bb5e", + "transactionHash": "0x32716ee082d70ad90f352753ab89f450c293b8e19dbc6a284fdbd98de85a6483", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96", - "transactionIndex": 11, - "gasUsed": "5311325", + "contractAddress": "0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB", + "transactionIndex": 1, + "gasUsed": "5264115", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd61b98a3ba8adaa999958db7b71be478529c171cdcf844f64b2da0854e140e0a", - "transactionHash": "0xd73596df9c81efa589d801e805445a1f49479e418e398dde2e7ae105f2f4bb5e", + "blockHash": "0x7f5a7a7f5710add21cffb6f9d723e3a8766d432776cdc4bb5efcfe4bee1ab58f", + "transactionHash": "0x32716ee082d70ad90f352753ab89f450c293b8e19dbc6a284fdbd98de85a6483", "logs": [], - "blockNumber": 367562402, - "cumulativeGasUsed": "6154130", + "blockNumber": 390053898, + "cumulativeGasUsed": "5264115", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 24, - "solcInputHash": "79ca35a0eb57a5a4e0af2a0fc5a1dbeb", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"DisabledMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"EmptyAddressInMarketTokenBalanceValidation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expectedMinBalance\",\"type\":\"uint256\"}],\"name\":\"InvalidMarketTokenBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"claimableFundingFeeAmount\",\"type\":\"uint256\"}],\"name\":\"InvalidMarketTokenBalanceForClaimableFunding\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"}],\"name\":\"InvalidMarketTokenBalanceForCollateralAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"InvalidSwapMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"swapPathLengh\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSwapPathLength\",\"type\":\"uint256\"}],\"name\":\"MaxSwapPathLengthExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__Exp2InputTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__LogInputTooSmall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivFixedPointOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnableToGetBorrowingFactorEmptyPoolUsd\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnableToGetFundingFactorEmptyOpenInterest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"marketAddress\",\"type\":\"address\"}],\"name\":\"getEnabledMarket\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"pnlFactorType\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"maximize\",\"type\":\"bool\"}],\"name\":\"getMarketTokenPrice\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"poolValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"longPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"shortPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"netPnl\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrowingFees\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFeePoolFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"impactPoolAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lentImpactPoolAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct MarketPoolValueInfo.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract MarketToken\",\"name\":\"marketToken\",\"type\":\"MarketToken\"}],\"name\":\"getMarketTokenSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"pnlFactorType\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"maximize\",\"type\":\"bool\"}],\"name\":\"getPoolValueInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"int256\",\"name\":\"poolValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"longPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"shortPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"netPnl\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrowingFees\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFeePoolFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"impactPoolAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lentImpactPoolAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct MarketPoolValueInfo.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"name\":\"getSwapPathMarkets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"marketAddress\",\"type\":\"address\"}],\"name\":\"validateEnabledMarket\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"}],\"name\":\"validateEnabledMarket\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"}],\"name\":\"validateMarketTokenBalance\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"_market\",\"type\":\"address\"}],\"name\":\"validateMarketTokenBalance\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props[]\",\"name\":\"markets\",\"type\":\"tuple[]\"}],\"name\":\"validateMarketTokenBalance\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"name\":\"validateSwapPath\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMathUD60x18__Exp2InputTooBig(uint256)\":[{\"notice\":\"Emitted when the input is greater than 192.\"}],\"PRBMathUD60x18__LogInputTooSmall(uint256)\":[{\"notice\":\"Emitted when the input is less than 1.\"}],\"PRBMath__MulDivFixedPointOverflow(uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/MarketUtils.sol\":\"MarketUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x615d20610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100cf5760003560e01c80630988a8f7146100d45780631450a879146100fd57806316ba20891461011f5780631ded168e1461014057806339b1348f146101535780635930015e146101665780635d95a47e1461017957806361a6d817146101995780637b3435fc146101ac5780637b672c9a146101bf5780637d494dc3146101d2578063b656ff7a146101f3578063c468d13514610213578063d2ab7dc014610233578063f2e2a4f514610253575b600080fd5b6100e76100e23660046153be565b610273565b6040516100f491906154a9565b60405180910390f35b81801561010957600080fd5b5061011d610118366004615621565b610330565b005b61013261012d366004615692565b610448565b6040519081526020016100f4565b61011d61014e3660046156af565b6104ac565b61011d6101613660046156e8565b61053a565b61011d6101743660046156af565b610581565b61018c6101873660046156af565b610599565b6040516100f4919061571e565b61011d6101a73660046156e8565b610631565b61011d6101ba3660046153be565b610703565b61011d6101cd36600461572c565b61082d565b6101e56101e03660046157d2565b610864565b6040516100f49291906158dd565b8180156101ff57600080fd5b5061011d61020e3660046158f2565b6108fd565b81801561021f57600080fd5b5061011d61022e366004615960565b610927565b81801561023f57600080fd5b5061011d61024e3660046159ab565b610a4c565b6102666102613660046157d2565b610c6c565b6040516100f49190615a06565b6060600082516001600160401b038111156102905761029061532d565b6040519080825280602002602001820160405280156102c957816020015b6102b66151c7565b8152602001906001900390816102ae5790505b50905060005b83518110156103265760008482815181106102ec576102ec615a15565b602002602001015190506103008682610ffb565b83838151811061031257610312615a15565b6020908102919091010152506001016102cf565b5090505b92915050565b60008061033f8786868661108c565b92509250506103558787876000015186866110f2565b866001600160a01b031663e2a4853a610372876000015186611202565b426040518363ffffffff1660e01b8152600401610390929190615a2b565b6020604051808303816000875af11580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d39190615a39565b508451604051635375a20760e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc891635375a2079161040f918a918690600401615a52565b60006040518083038186803b15801561042757600080fd5b505af415801561043b573d6000803e3d6000fd5b5050505050505050505050565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032a9190615a39565b60405163a8d8fff560e01b815260009073d727120ac811e9136D4a5D5C6219aEE37e2757859063a8d8fff5906104e89086908690600401615a76565b608060405180830381865af4158015610505573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105299190615a90565b90506105358382610631565b505050565b610549828283604001516112a8565b80606001516001600160a01b031681604001516001600160a01b03160361056e575050565b61057d828283606001516112a8565b5050565b600061058d8383610599565b9050610535838261053a565b6105a16151c7565b60405163a8d8fff560e01b815260009073d727120ac811e9136D4a5D5C6219aEE37e2757859063a8d8fff5906105dd9087908790600401615a76565b608060405180830381865af41580156105fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061e9190615a90565b905061062a8482610631565b9392505050565b80516001600160a01b0316610659576040516302fde0d760e11b815260040160405180910390fd5b6000826001600160a01b0316637ae1cfca61067784600001516114a6565b6040518263ffffffff1660e01b815260040161069591815260200190565b602060405180830381865afa1580156106b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d69190615af9565b905080156105355781516040516309f8c93760e01b81526106fa9190600401615b16565b60405180910390fd5b6000826001600160a01b031663bd02d0f560405160200161074c9060208082526014908201527309a82b0bea6ae82a0bea082a890be988a9c8ea8960631b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161078091815260200190565b602060405180830381865afa15801561079d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c19190615a39565b905080825111156107ea57815181604051639da3604360e01b81526004016106fa929190615a2b565b60005b825181101561082757600083828151811061080a5761080a615a15565b6020026020010151905061081e8582611528565b506001016107ed565b50505050565b60005b81518110156105355761085c8383838151811061084f5761084f615a15565b602002602001015161053a565b600101610830565b600061086e6151ee565b600061087d8960000151610448565b905060006108908b8b8b8b8b8b8b610c6c565b9050816000036108ba576108af68327cb2734119d3b7a9601e1b6115b1565b935091506108f19050565b80516000036108d0576000935091506108f19050565b60006108e9670de0b6b3a764000083600001518561161f565b945090925050505b97509795505050505050565b600061090e88888888888888611668565b905061091c888888846116af565b505050505050505050565b6000806109348584611736565b91509150816000146109cb5761095d85858561094f866115b1565b61095890615b40565b6118cc565b604051633a5d319360e21b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc89063e974c64c9061099a908790879087908790600401615b5c565b60006040518083038186803b1580156109b257600080fd5b505af41580156109c6573d6000803e3d6000fd5b505050505b846001600160a01b031663e2a4853a6109e385611f67565b426040518363ffffffff1660e01b8152600401610a01929190615a2b565b6020604051808303816000875af1158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190615a39565b505050505050565b6000610a59858484611fb6565b9050610a7e858585600001518660400151600186606001516000015160000151612359565b610aa1858585600001518660400151600086606001516020015160000151612359565b610ac4858585600001518660600151600186606001516000015160200151612359565b610ae7858585600001518660600151600086606001516020015160200151612359565b8251604084015160808301515151610b05928892889260019061241f565b610b2885858560000151866040015160008660800151602001516000015161241f565b610b4b85858560000151866060015160018660800151600001516020015161241f565b610b6e85858560000151866060015160008660800151602001516020015161241f565b610b8185846000015183604001516124e6565b50846001600160a01b031663e2a4853a610b9e8560000151612561565b426040518363ffffffff1660e01b8152600401610bbc929190615a2b565b6020604051808303816000875af1158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190615a39565b508251602082015160405163387a0f1360e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc89263387a0f1392610c409289929190600401615a52565b60006040518083038186803b158015610c5857600080fd5b505af415801561091c573d6000803e3d6000fd5b610c746151ee565b610c7c6151ee565b610c8b89898a60400151612599565b60808201526060880151610ca2908a908a90612599565b60a0820152610cb18684612637565b8160800151610cc09190615b85565b60c0820152610ccf8584612637565b8160a00151610cde9190615b85565b60e0820181905260c0820151610cfc91610cf791615b9c565b6115b1565b81526040805160608101825288815260208101889052908101869052610d258a8a83600161264e565b610100830152610d388a8a83600061264e565b8261010001818151610d4a9190615b9c565b9052506040516001600160a01b038b169063bd02d0f590610d9f906020016020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dd391815260200190565b602060405180830381865afa158015610df0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e149190615a39565b610e2a9068327cb2734119d3b7a9601e1b615baf565b6101208301819052610100830151610e4691610cf791906126a4565b82518390610e55908390615bc2565b905250610e678a8a8a600188156126bd565b60208301819052895160c0840151610e86928d9291600191908a612749565b6020830152610e9a8a8a8a600088156126bd565b60408301819052895160e0840151610eb9928d9291600091908a612749565b604083018190526020830151610ecf9190615bc2565b606083018190528251610ee29190615bea565b82528851610ef1908b90612799565b6101408301526000610f04898615612637565b836101400151610f149190615b85565b9050610f1f816115b1565b83518490610f2e908390615bea565b90525089516001600160a01b038c169063bd02d0f590610f4d906127a6565b6040518263ffffffff1660e01b8152600401610f6b91815260200190565b602060405180830381865afa158015610f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fac9190615a39565b6101608401526000610fbe8a87612637565b846101600151610fce9190615b85565b9050610fd9816115b1565b84518590610fe8908390615bc2565b905250929b9a5050505050505050505050565b6110036151c7565b60405163a8d8fff560e01b815260009073d727120ac811e9136D4a5D5C6219aEE37e2757859063a8d8fff59061103f9087908790600401615a76565b608060405180830381865af415801561105c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110809190615a90565b905061062a84826127e7565b6000806000806110a18888600001518761282e565b905060006110b18989898961285a565b905060006110c48a8a6000015189612a7a565b905060006110d28385615b85565b905060006110e08284615b9c565b9c919b50929950975050505050505050565b6000856001600160a01b031663340dbab361110d8686612ad0565b846040518363ffffffff1660e01b815260040161112b929190615a2b565b6020604051808303816000875af115801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e9190615a39565b60405163d206b70560e01b81526001600160a01b038088166004830152861660248201528415156044820152606481018490526084810182905290915073C1bd1ad41cda5C5c5953766CbA5c375c85407cc89063d206b7059060a40160006040518083038186803b1580156111e257600080fd5b505af41580156111f6573d6000803e3d6000fd5b50505050505050505050565b60006040516020016112549060208082526026908201527f43554d554c41544956455f424f52524f57494e475f464143544f525f5550444160408201526515115117d05560d21b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0385169082015282151560608201526080015b60405160208183030381529060405280519060200120905092915050565b81516001600160a01b031615806112c657506001600160a01b038116155b156112e957815160405163e474a42560e01b81526106fa91908390600401615a76565b81516040516370a0823160e01b81526000916001600160a01b038416916370a082319161131891600401615b16565b602060405180830381865afa158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190615a39565b90506000611368858585612b11565b9050808210156113945783516040516333a1ea6b60e01b81526106fa9190859085908590600401615b5c565b60006113a886866000015186600180612e2b565b90506113bd8686600001518660006001612e2b565b6113c79082615b9c565b9050808310156113f357845160405163808c464f60e01b81526106fa9190869086908590600401615b5c565b6000866001600160a01b031663bd02d0f5611412886000015188612eb1565b6040518263ffffffff1660e01b815260040161143091815260200190565b602060405180830381865afa15801561144d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114719190615a39565b90508084101561149d578551604051639dd026db60e01b81526106fa9190879087908590600401615b5c565b50505050505050565b60006040516020016114de906020808252601290820152711254d7d3505492d15517d11254d05093115160721b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60405163a8d8fff560e01b815260009073d727120ac811e9136D4a5D5C6219aEE37e2757859063a8d8fff5906115649086908690600401615a76565b608060405180830381865af4158015611581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a59190615a90565b905061053583826127e7565b60006001600160ff1b0382111561161b5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016106fa565b5090565b6000806116358561162f86612f2c565b85612f3f565b90506000841361165657611648816115b1565b61165190615b40565b61165f565b61165f816115b1565b95945050505050565b600080611676898989612f4c565b905061168286866126a4565b61168c9082615baf565b905061169884846126a4565b6116a29082615b9c565b9998505050505050505050565b6000846001600160a01b031663e2a4853a6116ca8686612f63565b846040518363ffffffff1660e01b81526004016116e8929190615a2b565b6020604051808303816000875af1158015611707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172b9190615a39565b90505b949350505050565b60008060006117458585612f98565b90508060000361175a576000925090506118c5565b6000856001600160a01b031663bd02d0f561177487613011565b6040518263ffffffff1660e01b815260040161179291815260200190565b602060405180830381865afa1580156117af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d39190615a39565b9050806000036117e957506000925090506118c5565b6000866001600160a01b031663bd02d0f561180388613063565b6040518263ffffffff1660e01b815260040161182191815260200190565b602060405180830381865afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190615a39565b905080831161187a57600083945094505050506118c5565b60006118868285615baf565b9050600061189489896130a6565b905060006118a282866126a4565b9050828111156118af5750815b806118ba8188615baf565b975097505050505050505b9250929050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915261190782612f2c565b60408201526000821215611c625761191e8361313e565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b9190615a39565b6060820181905260408201511115611bac57806060015181604001516119b19190615baf565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a916119e69190600090600401615a2b565b6020604051808303816000875af1158015611a05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a299190615a39565b5073C1bd1ad41cda5C5c5953766CbA5c375c85407cc863555a99798585611a5385606001516115b1565b60006040518563ffffffff1660e01b8152600401611a749493929190615b5c565b60006040518083038186803b158015611a8c57600080fd5b505af4158015611aa0573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611abc856127a6565b83608001516040518363ffffffff1660e01b8152600401611ade929190615a2b565b6020604051808303816000875af1158015611afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b219190615a39565b8160a001818152505073C1bd1ad41cda5C5c5953766CbA5c375c85407cc8634ddb3d818585611b5385608001516115b1565b8560a001516040518563ffffffff1660e01b8152600401611b779493929190615b5c565b60006040518083038186803b158015611b8f57600080fd5b505af4158015611ba3573d6000803e3d6000fd5b50505050611f60565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611bdd92600401615a2b565b6020604051808303816000875af1158015611bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c209190615a39565b60a0820181905260405163555a997960e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc89163555a997991611b7791889188918891600401615b5c565b611c6b836127a6565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611cb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdc9190615a39565b6060820181905260408201511115611ea75780606001518160400151611d029190615baf565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a91611d3a9190600090600401615a2b565b6020604051808303816000875af1158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d9190615a39565b5073C1bd1ad41cda5C5c5953766CbA5c375c85407cc8634ddb3d818585611da785606001516115b1565b60006040518563ffffffff1660e01b8152600401611dc89493929190615b5c565b60006040518083038186803b158015611de057600080fd5b505af4158015611df4573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611e108561313e565b83608001516040518363ffffffff1660e01b8152600401611e32929190615a2b565b6020604051808303816000875af1158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190615a39565b8160a001818152505073C1bd1ad41cda5C5c5953766CbA5c375c85407cc863555a99798585611b5385608001516115b1565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611edb92600401615a2b565b6020604051808303816000875af1158015611efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1e9190615a39565b60a08201819052604051634ddb3d8160e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc891634ddb3d8191610c4091889188918891600401615b5c565b5050505050565b60006040516020016114de9060208082526023908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554454460408201526217d05560ea1b606082015260800190565b611fbe61524f565b611fc661524f565b611fce61528b565b6000611fe28660400151876060015161317f565b9050611ffa87876000015188604001516001856131ae565b82515152855160608701516120139189916001856131ae565b825151602001528551604087015161202f9189916000856131ae565b825160200151528551606087015161204b9189916000856131ae565b825160209081015181019190915282515190810151905161206c9190615b9c565b602080840191909152825181015190810151905161208a9190615b9c565b6040830152602082015115806120a257506040820151155b156120b25782935050505061062a565b6120c08787600001516131cb565b606083018190528651602084015160408501516120e1938b939291906131e6565b604086015215158085526020850191909152612101578160400151612107565b81602001515b608083018190526020840151606084015161212b929161212691615b85565b6126a4565b60a0830181905261213d908290615c27565b60a083015282511561218e5760a0820151825151516020840151612162929190612f3f565b60c083015260a082015182515160209081015190840151612184929190612f3f565b60e08301526121d4565b60a08201518251602001515160408401516121aa929190612f3f565b60c083015260a08201518251602090810151015160408401516121ce929190612f3f565b60e08301525b8251156122925760c08201518251515160208088015101516121f992919060016138ef565b6060840151515260e082015182515160209081015160408801519091015161222492919060016138ef565b83606001516000015160200181815250506122528260c00151836040015187602001516020015160006138ef565b83608001516020015160000181815250506122808260e00151836040015187604001516020015160006138ef565b6080840151602090810151015261234e565b6122b78260c001518360000151602001516000015187602001516020015160016138ef565b83606001516020015160000181815250506122ed8260e001518360000151602001516020015187604001516020015160016138ef565b836060015160200151602001818152505061231b8260c00151836020015187602001516020015160006138ef565b6080840151515260e082015160208084015160408801519091015161234392919060006138ef565b608084015151602001525b509095945050505050565b8015610a44576000866001600160a01b0316633dbacd1a61237b878787613957565b846040518363ffffffff1660e01b8152600401612399929190615a2b565b6020604051808303816000875af11580156123b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dc9190615a39565b6040516261034760e41b815290915073C1bd1ad41cda5C5c5953766CbA5c375c85407cc89063061034709061040f90899089908990899089908990600401615c3b565b8015610a44576000866001600160a01b0316633dbacd1a6124418787876139f8565b846040518363ffffffff1660e01b815260040161245f929190615a2b565b6020604051808303816000875af115801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a29190615a39565b604051636d6b205960e01b815290915073C1bd1ad41cda5C5c5953766CbA5c375c85407cc890636d6b20599061040f90899089908990899089908990600401615c3b565b6000836001600160a01b0316633e49bed061250085613a45565b846040518363ffffffff1660e01b815260040161251e929190615a2b565b6020604051808303816000875af115801561253d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190615a39565b60006040516020016114de9060208082526012908201527111955391125391d7d554111055115117d05560721b604082015260600190565b6000806125ae8460400151856060015161317f565b905080856001600160a01b031663bd02d0f56125ce876000015187613a88565b6040518263ffffffff1660e01b81526004016125ec91815260200190565b602060405180830381865afa158015612609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262d9190615a39565b61165f9190615c27565b60008161264557825161062a565b50506020015190565b60008061265c868685613ab9565b9050600061266c8787878761108c565b50509050600061268188886000015187612f4c565b90508061268e84846126a4565b6126989190615baf565b98975050505050505050565b600061062a838368327cb2734119d3b7a9601e1b612f3f565b6000806126ce610cf7888887613ab9565b905060006126dd888887613b17565b90508115806126ea575080155b156126fa5760009250505061165f565b6000612707878787613b5e565b90506000612718610cf78385615b85565b90506000876127305761272b8286615bea565b61273a565b61273a8583615bea565b9b9a5050505050505050505050565b60008084121561275a57508261278f565b600061276888848989613b97565b90506000612779610cf786846126a4565b9050808613612788578561278a565b805b925050505b9695505050505050565b60008061165f8484611736565b60006040516020016114de906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b6127f18282610631565b80606001516001600160a01b031681604001516001600160a01b03160361057d5780516040516332e6f44d60e21b81526106fa9190600401615b16565b60008061283c858585613bee565b90508060000361285057600091505061062a565b61165f8142615baf565b60008061286986868686613c09565b90508060000361287d57600091505061172e565b6000866001600160a01b0316637ae1cfca6040516020016128db9060208082526023908201527f534b49505f424f52524f57494e475f4645455f464f525f534d414c4c45525f5360408201526249444560e81b606082015260800190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161290f91815260200190565b602060405180830381865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129509190615af9565b905080156129b857600061296688886001613ab9565b9050600061297689896000613ab9565b905085801561298457508082105b1561299657600094505050505061172e565b851580156129a357508181105b156129b557600094505050505061172e565b50505b60006129c8888888886000613c45565b9050806000036129eb57604051630d5f5aef60e31b815260040160405180910390fd5b60006129fc89896000015188613cbe565b90508015612a1d57612a12898988878686613cd9565b94505050505061172e565b6000612a2e8a8a6000015189613e88565b90506000612a3c8683613ea3565b90506000612a4a8286613f02565b90506000612a5d8d8d600001518c613f10565b9050612a6982826126a4565b9d9c50505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a958585612ad0565b6040518263ffffffff1660e01b8152600401612ab391815260200190565b602060405180830381865afa15801561253d573d6000803e3d6000fd5b6000604051602001611254906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b6000612b4c6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b846001600160a01b031663bd02d0f5612b69866000015186613a88565b6040518263ffffffff1660e01b8152600401612b8791815260200190565b602060405180830381865afa158015612ba4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc89190615a39565b81528351612bd890869085613f2b565b602082015283516001600160a01b0386169063bd02d0f590612bfa9086613f46565b6040518263ffffffff1660e01b8152600401612c1891815260200190565b602060405180830381865afa158015612c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c599190615a39565b604082015283516001600160a01b0386169063bd02d0f590612c7b9086613f87565b6040518263ffffffff1660e01b8152600401612c9991815260200190565b602060405180830381865afa158015612cb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cda9190615a39565b606082015283516001600160a01b0386169063bd02d0f590612cfc9086613fc1565b6040518263ffffffff1660e01b8152600401612d1a91815260200190565b602060405180830381865afa158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5b9190615a39565b608082015283516001600160a01b0386169063bd02d0f590612d7d9086613ffe565b6040518263ffffffff1660e01b8152600401612d9b91815260200190565b602060405180830381865afa158015612db8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddc9190615a39565b60a0820181905260808201516060830151604084015160208501518551612e039190615b9c565b612e0d9190615b9c565b612e179190615b9c565b612e219190615b9c565b61165f9190615b9c565b600081866001600160a01b031663bd02d0f5612e48888888614034565b6040518263ffffffff1660e01b8152600401612e6691815260200190565b602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea79190615a39565b61278f9190615c27565b6000604051602001612eef9060208082526018908201527710d31052535050931157d1955391125391d7d05353d5539560421b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800161128a565b60008082121561161b578160000361032a565b600061172e848484614068565b6000836001600160a01b031663bd02d0f5612a9585855b6000604051602001611254906020808252600f908201526e544f54414c5f424f52524f57494e4760881b604082015260600190565b6000826001600160a01b031663bd02d0f5612fb28461313e565b6040518263ffffffff1660e01b8152600401612fd091815260200190565b602060405180830381865afa158015612fed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062a9190615a39565b60006040516020016114de9060208082526026908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554494f6040820152654e5f5241544560d01b606082015260800190565b60006040516020016114de906020808252601f908201527f4d494e5f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e5400604082015260600190565b600080836001600160a01b031663bd02d0f56130c185611f67565b6040518263ffffffff1660e01b81526004016130df91815260200190565b602060405180830381865afa1580156130fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131209190615a39565b90508060000361313457600091505061032a565b61172e8142615baf565b60006040516020016114de906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000816001600160a01b0316836001600160a01b0316146131a15760016131a4565b60025b60ff169392505050565b600081866001600160a01b031663bd02d0f5612e48888888614152565b600080836001600160a01b031663bd02d0f56130c185612561565b6000806000613241604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61324b8787614185565b81526132578688615b9c565b8160200181815250506132996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b896001600160a01b031663bd02d0f56132b18b6141a7565b6040518263ffffffff1660e01b81526004016132cf91815260200190565b602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190615a39565b6040820152815115801561332657506040810151155b1561333e5760006001600094509450945050506138e4565b8160200151600003613363576040516311423d9560e01b815260040160405180910390fd5b61336d8a8a6141f5565b60608301819052825161337f91613ea3565b6080830181905260208301516133959190613f02565b60a08301526040810151600003613465576133b08a8a61420f565b604083015260006001600160a01b038b1663bd02d0f56133cf8c614229565b6040518263ffffffff1660e01b81526004016133ed91815260200190565b602060405180830381865afa15801561340a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342e9190615a39565b905060006134448460a0015185604001516126a4565b9050818111156134515750805b955050508587119250600091506138e49050565b61346f8a8a61426c565b60c0830181905261347f90612f2c565b60e08301526001600160a01b038a1663bd02d0f561349c8b614286565b6040518263ffffffff1660e01b81526004016134ba91815260200190565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb9190615a39565b81526001600160a01b038a1663bd02d0f56135158b6142c8565b6040518263ffffffff1660e01b815260040161353391815260200190565b602060405180830381865afa158015613550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135749190615a39565b602082015260c082015161010083018190526000908190811280156135985750888a115b806135b1575060008460c001511280156135b157508989115b905080156135e957825160a085015111156135cf57600191506135ee565b82602001518460a0015110156135e457600291505b6135ee565b600191505b600182600281111561360257613602615c76565b0361365f576000613612896115b1565b613627610cf78760a0015187604001516126a4565b6136319190615c8c565b9050898b10156136475761364481615b40565b90505b808560c001516136579190615bc2565b610100860152505b600282600281111561367357613673615c76565b148015613683575060e084015115155b15613790578b6001600160a01b031663bd02d0f56136a08d61430b565b6040518263ffffffff1660e01b81526004016136be91815260200190565b602060405180830381865afa1580156136db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ff9190615a39565b60608401819052600090613714908a90615b85565b9050808560e00151116137485761372e8560e001516115b1565b8560c0015161373d9190615cbc565b61010086015261378e565b60006137578660e001516115b1565b8660c001516137669190615cbc565b90508061377c838860e00151610cf79190615baf565b6137869190615c8c565b610100870152505b505b8b6001600160a01b031663bd02d0f56137a88d614359565b6040518263ffffffff1660e01b81526004016137c691815260200190565b602060405180830381865afa1580156137e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138079190615a39565b60808401526001600160a01b038c1663bd02d0f56138248d614229565b6040518263ffffffff1660e01b815260040161384291815260200190565b602060405180830381865afa15801561385f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138839190615a39565b60a0840181905261010085015161389c9160009061439c565b6101008501819052608084015160a08501516138b992919061439c565b61012085018190526138ca90612f2c565b600085610120015113856101000151965096509650505050505b955095509592505050565b60008415806138fc575083155b156139095750600061172e565b60006139338661392c66038d7ea4c6800068327cb2734119d3b7a9601e1b615b85565b87866143fc565b9050821561394d576139458185614423565b91505061172e565b6139458482615c27565b6000604051602001613998906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016139989060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b60006040516020016114de906020808252601f908201527f53415645445f46554e44494e475f464143544f525f5045525f5345434f4e4400604082015260600190565b6000604051602001612eef906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b600080613ace8460400151856060015161317f565b90506000613ae7868660000151876040015187866131ae565b90506000613b00878760000151886060015188876131ae565b9050613b0c8183615b9c565b979650505050505050565b600080613b2c8460400151856060015161317f565b90506000613b4586866000015187604001518786614446565b90506000613b0087876000015188606001518887614446565b60008215613b7f5781613b72578351613b78565b83602001515b905061062a565b81613b8e57836020015161172e565b50509051919050565b6000846001600160a01b031663bd02d0f5613bb3868686614463565b6040518263ffffffff1660e01b8152600401613bd191815260200190565b602060405180830381865afa158015611707573d6000803e3d6000fd5b6000836001600160a01b031663bd02d0f5612a958585611202565b6000808215613c3a576000613c1f878786613b17565b855160200151909150613c329082615b85565b91505061172b565b61278f868685613ab9565b60008083613c57578560600151613c5d565b85604001515b90506000613c6c888884612599565b905060008415613c9a5785613c8957866040015160200151613c93565b8660200151602001515b9050613cb4565b85613caa57604087015151613cb1565b6020870151515b90505b6116a28183615b85565b6000836001600160a01b031663bd02d0f5612a9585856144d7565b600080613ce98888888888614511565b90506000886001600160a01b031663bd02d0f5613d0a8a600001518a61453f565b6040518263ffffffff1660e01b8152600401613d2891815260200190565b602060405180830381865afa158015613d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d699190615a39565b90506000613d7783836126a4565b90508483118015613d9357508468327cb2734119d3b7a9601e1b115b1561278a576000613da48685615baf565b905060008b6001600160a01b031663bd02d0f5613dc58d600001518d61457a565b6040518263ffffffff1660e01b8152600401613de391815260200190565b602060405180830381865afa158015613e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e249190615a39565b9050600084821115613e3d57613e3a8583615baf565b90505b6000613e558968327cb2734119d3b7a9601e1b615baf565b905080613e628584615b85565b613e6c9190615c27565b613e769086615b9c565b9e9d5050505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a9585856145ca565b600068327cb2734119d3b7a9601e1b831015613ec15750600061032a565b68327cb2734119d3b7a9601e1b8203613edb57508161032a565b6000613ef7613ee985614609565b613ef285614609565b61461a565b905061172e8161465c565b600061062a8383600061466d565b6000836001600160a01b031663bd02d0f5612a9585856146b5565b6000836001600160a01b031663bd02d0f5612a9585856146eb565b6000604051602001612eef906020808252601b908201527a10d31052535050931157d0d3d31310551154905317d05353d55395602a1b604082015260600190565b6000604051602001612eef9060208082526014908201527310d31052535050931157d1915157d05353d5539560621b604082015260600190565b6000604051602001612eef9060208082526017908201527610d31052535050931157d55257d1915157d05353d55395604a1b604082015260600190565b6000604051602001612eef9060208082526010908201526f10519192531250551157d49155d0549160821b604082015260600190565b6000604051602001613998906020808252600e908201526d434f4c4c41544552414c5f53554d60901b604082015260600190565b60008080600019858709858702925082811083820303915050806000036140a25783828161409857614098615c11565b049250505061062a565b8084116140e95760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016106fa565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001613998906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b600081831161419d576141988383615baf565b61062a565b61062a8284615baf565b60006040516020016114de9060208082526022908201527f46554e44494e475f494e4352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b6000826001600160a01b031663bd02d0f5612fb284614728565b6000826001600160a01b031663bd02d0f5612fb284614765565b60006040516020016114de906020808252601d908201527f4d41585f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000826001600160a01b031663dc97d962612fb284613a45565b60006040516020016114de906020808252601c908201527b5448524553484f4c445f464f525f535441424c455f46554e44494e4760201b604082015260600190565b60006040516020016114de906020808252601e908201527f5448524553484f4c445f464f525f44454352454153455f46554e44494e470000604082015260600190565b60006040516020016114de9060208082526022908201527f46554e44494e475f44454352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b60006040516020016114de906020808252601d908201527f4d494e5f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000806143a885612f2c565b9050838110156143b55750825b828111156143c05750815b600085156143e3576143d4610cf787612f2c565b6143de9087615cbc565b6143e6565b60015b9050806143f2836115b1565b61278f9190615c8c565b60008115614418576144118585856001614799565b905061172e565b61172b858585614068565b60008160016144328286615b9c565b61443c9190615baf565b61062a9190615c27565b600081866001600160a01b031663bd02d0f5612e488888886147ea565b6000604051602001614497906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a0016139d9565b60006040516020016112549060208082526014908201527327a82a24a6a0a62faaa9a0a3a2afa320a1aa27a960611b604082015260600190565b60008061452387876000015187614827565b9050600061453184836126a4565b905060006116a28683613f02565b6000604051602001611254906020808252601590820152742120a9a2afa127a92927aba4a723afa320a1aa27a960591b604082015260600190565b60006040516020016112549060208082526024908201527f41424f56455f4f5054494d414c5f55534147455f424f52524f57494e475f464160408201526321aa27a960e11b606082015260800190565b6000604051602001611254906020808252601990820152782127a92927aba4a723afa2ac2827a722a72a2fa320a1aa27a960391b604082015260600190565b600061032a64e8d4a5100083615c27565b60008260000361464257811561463157600061463b565b670de0b6b3a76400005b905061032a565b61062a61465761465185614842565b846148f8565b614904565b600061032a64e8d4a5100083615b85565b60008360000361467f5750600061062a565b811561469e57613b788468327cb2734119d3b7a9601e1b856001614799565b61172e8468327cb2734119d3b7a9601e1b85614068565b60006040516020016112549060208082526010908201526f2127a92927aba4a723afa320a1aa27a960811b604082015260600190565b6000604051602001612eef9060208082526017908201527614d5d05417d253541050d517d413d3d317d05353d55395604a1b604082015260600190565b60006040516020016114de90602080825260179082015276232aa72224a723afa2ac2827a722a72a2fa320a1aa27a960491b604082015260600190565b60006040516020016114de906020808252600e908201526d232aa72224a723afa320a1aa27a960911b604082015260600190565b6000806147a7868686614068565b905060018360028111156147bd576147bd615c76565b1480156147da5750600084806147d5576147d5615c11565b868809115b1561172b5761278f600182615b9c565b6000604051602001613998906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b6000836001600160a01b031663bd02d0f5612a95858561494a565b6000670de0b6b3a764000082101561487057604051633621413760e21b8152600481018390526024016106fa565b6000614885670de0b6b3a7640000840461498c565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff1981016148ae575050919050565b6706f05b59d3b200005b80156148f057670de0b6b3a7640000828002049150671bc16d674ec8000082106148e8579283019260019190911c905b60011c6148b8565b505050919050565b600061062a8383614a6f565b6000680a688906bd8b000000821061493257604051634a4f26f160e01b8152600481018390526024016106fa565b670de0b6b3a7640000604083901b0461062a81614b35565b6000604051602001611254906020808252601c908201527b27a822a72fa4a72a22a922a9aa2fa922a9a2a92b22afa320a1aa27a960211b604082015260600190565b6000600160801b82106149ac57608091821c916149a99082615b9c565b90505b600160401b82106149ca57604091821c916149c79082615b9c565b90505b600160201b82106149e857602091821c916149e59082615b9c565b90505b620100008210614a0557601091821c91614a029082615b9c565b90505b6101008210614a2157600891821c91614a1e9082615b9c565b90505b60108210614a3c57600491821c91614a399082615b9c565b90505b60048210614a5757600291821c91614a549082615b9c565b90505b60028210614a6a5761032a600182615b9c565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110614ab35760405163698d9a0160e11b8152600481018290526024016106fa565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff8211905082600003614af15780670de0b6b3a764000085040194505050505061032a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b821615614b555768016a09e667f3bcc9090260401c5b6001603e1b821615614b70576801306fe0a31b7152df0260401c5b6001603d1b821615614b8b576801172b83c7d517adce0260401c5b6001603c1b821615614ba65768010b5586cf9890f62a0260401c5b6001603b1b821615614bc1576801059b0d31585743ae0260401c5b6001603a1b821615614bdc57680102c9a3e778060ee70260401c5b600160391b821615614bf75768010163da9fb33356d80260401c5b600160381b821615614c1257680100b1afa5abcbed610260401c5b600160371b821615614c2d5768010058c86da1c09ea20260401c5b600160361b821615614c48576801002c605e2e8cec500260401c5b600160351b821615614c6357680100162f3904051fa10260401c5b600160341b821615614c7e576801000b175effdc76ba0260401c5b600160331b821615614c9957680100058ba01fb9f96d0260401c5b600160321b821615614cb45768010002c5cc37da94920260401c5b600160311b821615614ccf576801000162e525ee05470260401c5b600160301b821615614cea5768010000b17255775c040260401c5b6001602f1b821615614d05576801000058b91b5bc9ae0260401c5b6001602e1b821615614d2057680100002c5c89d5ec6d0260401c5b6001602d1b821615614d3b5768010000162e43f4f8310260401c5b6001602c1b821615614d5657680100000b1721bcfc9a0260401c5b6001602b1b821615614d715768010000058b90cf1e6e0260401c5b6001602a1b821615614d8c576801000002c5c863b73f0260401c5b600160291b821615614da757680100000162e430e5a20260401c5b600160281b821615614dc2576801000000b1721835510260401c5b600160271b821615614ddd57680100000058b90c0b490260401c5b600160261b821615614df85768010000002c5c8601cc0260401c5b600160251b821615614e13576801000000162e42fff00260401c5b600160241b821615614e2e5768010000000b17217fbb0260401c5b600160231b821615614e49576801000000058b90bfce0260401c5b600160221b821615614e6457680100000002c5c85fe30260401c5b600160211b821615614e7f5768010000000162e42ff10260401c5b600160201b821615614e9a57680100000000b17217f80260401c5b6380000000821615614eb55768010000000058b90bfc0260401c5b6340000000821615614ed0576801000000002c5c85fe0260401c5b6320000000821615614eeb57680100000000162e42ff0260401c5b6310000000821615614f06576801000000000b17217f0260401c5b6308000000821615614f2157680100000000058b90c00260401c5b6304000000821615614f3c5768010000000002c5c8600260401c5b6302000000821615614f57576801000000000162e4300260401c5b6301000000821615614f725768010000000000b172180260401c5b62800000821615614f8c576801000000000058b90c0260401c5b62400000821615614fa657680100000000002c5c860260401c5b62200000821615614fc05768010000000000162e430260401c5b62100000821615614fda57680100000000000b17210260401c5b62080000821615614ff45768010000000000058b910260401c5b6204000082161561500e576801000000000002c5c80260401c5b6202000082161561502857680100000000000162e40260401c5b620100008216156150415761b172600160401b010260401c5b618000821615615059576158b9600160401b010260401c5b61400082161561507157612c5d600160401b010260401c5b6120008216156150895761162e600160401b010260401c5b6110008216156150a157610b17600160401b010260401c5b6108008216156150b95761058c600160401b010260401c5b6104008216156150d1576102c6600160401b010260401c5b6102008216156150e957610163600160401b010260401c5b6101008216156151005760b1600160401b010260401c5b6080821615615116576059600160401b010260401c5b604082161561512c57602c600160401b010260401c5b6020821615615142576016600160401b010260401c5b601082161561515857600b600160401b010260401c5b600882161561516e576006600160401b010260401c5b6004821615615184576003600160401b010260401c5b600282161561519a576001600160401b010260401c5b60018216156151b0576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060001515815260200160008152602001600081526020016152796152d6565b81526020016152866152d6565b905290565b60405180610100016040528061529f6152d6565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60408051608081018252600091810182815260608201929092529081908152602001615286604051806040016040528060008152602001600081525090565b6001600160a01b038116811461532a57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156153655761536561532d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156153935761539361532d565b604052919050565b60006001600160401b038211156153b4576153b461532d565b5060051b60200190565b600080604083850312156153d157600080fd5b82356153dc81615315565b915060208301356001600160401b038111156153f757600080fd5b8301601f8101851361540857600080fd5b803561541b6154168261539b565b61536b565b8082825260208201915060208360051b85010192508783111561543d57600080fd5b6020840193505b8284101561546857833561545781615315565b825260209384019390910190615444565b809450505050509250929050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b602080825282518282018190526000918401906040840190835b8181101561234e576154d6838551615476565b60209390930192608092909201916001016154c3565b6000608082840312156154fe57600080fd5b615506615343565b9050813561551381615315565b8152602082013561552381615315565b6020820152604082013561553681615315565b6040820152606082013561554981615315565b606082015292915050565b60006040828403121561556657600080fd5b604080519081016001600160401b03811182821017156155885761558861532d565b604052823581526020928301359281019290925250919050565b600060c082840312156155b457600080fd5b604051606081016001600160401b03811182821017156155d6576155d661532d565b6040529050806155e68484615554565b81526155f58460408501615554565b60208201526156078460808501615554565b60408201525092915050565b801515811461532a57600080fd5b60008060008060006101a0868803121561563a57600080fd5b853561564581615315565b9450602086013561565581615315565b935061566487604088016154ec565b92506156738760c088016155a2565b915061018086013561568481615613565b809150509295509295909350565b6000602082840312156156a457600080fd5b813561062a81615315565b600080604083850312156156c257600080fd5b82356156cd81615315565b915060208301356156dd81615315565b809150509250929050565b60008060a083850312156156fb57600080fd5b823561570681615315565b915061571584602085016154ec565b90509250929050565b6080810161032a8284615476565b6000806040838503121561573f57600080fd5b823561574a81615315565b915060208301356001600160401b0381111561576557600080fd5b8301601f8101851361577657600080fd5b80356157846154168261539b565b8082825260208201915060208360071b8501019250878311156157a657600080fd5b6020840193505b82841015615468576157bf88856154ec565b82526020820191506080840193506157ad565b60008060008060008060006101a0888a0312156157ee57600080fd5b87356157f981615315565b96506158088960208a016154ec565b95506158178960a08a01615554565b94506158268960e08a01615554565b9350615836896101208a01615554565b9250610160880135915061018088013561584f81615613565b8091505092959891949750929550565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008101516101008301526101208101516101208301526101408101516101408301526101608101516101608301525050565b8281526101a0810161062a602083018461585f565b600080600080600080600060e0888a03121561590d57600080fd5b873561591881615315565b9650602088013561592881615315565b9550604088013561593881615613565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b60008060006060848603121561597557600080fd5b833561598081615315565b9250602084013561599081615315565b915060408401356159a081615315565b809150509250925092565b60008060008061018085870312156159c257600080fd5b84356159cd81615315565b935060208501356159dd81615315565b92506159ec86604087016154ec565b91506159fb8660c087016155a2565b905092959194509250565b610180810161032a828461585f565b634e487b7160e01b600052603260045260246000fd5b918252602082015260400190565b600060208284031215615a4b57600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0392831681529116602082015260400190565b60006080828403128015615aa357600080fd5b50615aac615343565b8251615ab781615315565b81526020830151615ac781615315565b60208201526040830151615ada81615315565b60408201526060830151615aed81615315565b60608201529392505050565b600060208284031215615b0b57600080fd5b815161062a81615613565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201615b5557615b55615b2a565b5060000390565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b808202811582820484141761032a5761032a615b2a565b8082018082111561032a5761032a615b2a565b8181038181111561032a5761032a615b2a565b8082018281126000831280158216821582161715615be257615be2615b2a565b505092915050565b8181036000831280158383131683831282161715615c0a57615c0a615b2a565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600082615c3657615c36615c11565b500490565b6001600160a01b039687168152948616602086015292909416604084015215156060830152608082019290925260a081019190915260c00190565b634e487b7160e01b600052602160045260246000fd5b80820260008212600160ff1b84141615615ca857615ca8615b2a565b818105831482151761032a5761032a615b2a565b600082615ccb57615ccb615c11565b600160ff1b821460001984141615615ce557615ce5615b2a565b50059056fea264697066735822122068c56c92b780c3694e90a9239b6e8532ace780972d05932a36bec2715eedb8b964736f6c634300081d0033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100cf5760003560e01c80630988a8f7146100d45780631450a879146100fd57806316ba20891461011f5780631ded168e1461014057806339b1348f146101535780635930015e146101665780635d95a47e1461017957806361a6d817146101995780637b3435fc146101ac5780637b672c9a146101bf5780637d494dc3146101d2578063b656ff7a146101f3578063c468d13514610213578063d2ab7dc014610233578063f2e2a4f514610253575b600080fd5b6100e76100e23660046153be565b610273565b6040516100f491906154a9565b60405180910390f35b81801561010957600080fd5b5061011d610118366004615621565b610330565b005b61013261012d366004615692565b610448565b6040519081526020016100f4565b61011d61014e3660046156af565b6104ac565b61011d6101613660046156e8565b61053a565b61011d6101743660046156af565b610581565b61018c6101873660046156af565b610599565b6040516100f4919061571e565b61011d6101a73660046156e8565b610631565b61011d6101ba3660046153be565b610703565b61011d6101cd36600461572c565b61082d565b6101e56101e03660046157d2565b610864565b6040516100f49291906158dd565b8180156101ff57600080fd5b5061011d61020e3660046158f2565b6108fd565b81801561021f57600080fd5b5061011d61022e366004615960565b610927565b81801561023f57600080fd5b5061011d61024e3660046159ab565b610a4c565b6102666102613660046157d2565b610c6c565b6040516100f49190615a06565b6060600082516001600160401b038111156102905761029061532d565b6040519080825280602002602001820160405280156102c957816020015b6102b66151c7565b8152602001906001900390816102ae5790505b50905060005b83518110156103265760008482815181106102ec576102ec615a15565b602002602001015190506103008682610ffb565b83838151811061031257610312615a15565b6020908102919091010152506001016102cf565b5090505b92915050565b60008061033f8786868661108c565b92509250506103558787876000015186866110f2565b866001600160a01b031663e2a4853a610372876000015186611202565b426040518363ffffffff1660e01b8152600401610390929190615a2b565b6020604051808303816000875af11580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d39190615a39565b508451604051635375a20760e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__91635375a2079161040f918a918690600401615a52565b60006040518083038186803b15801561042757600080fd5b505af415801561043b573d6000803e3d6000fd5b5050505050505050505050565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032a9190615a39565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906104e89086908690600401615a76565b608060405180830381865af4158015610505573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105299190615a90565b90506105358382610631565b505050565b610549828283604001516112a8565b80606001516001600160a01b031681604001516001600160a01b03160361056e575050565b61057d828283606001516112a8565b5050565b600061058d8383610599565b9050610535838261053a565b6105a16151c7565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906105dd9087908790600401615a76565b608060405180830381865af41580156105fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061e9190615a90565b905061062a8482610631565b9392505050565b80516001600160a01b0316610659576040516302fde0d760e11b815260040160405180910390fd5b6000826001600160a01b0316637ae1cfca61067784600001516114a6565b6040518263ffffffff1660e01b815260040161069591815260200190565b602060405180830381865afa1580156106b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d69190615af9565b905080156105355781516040516309f8c93760e01b81526106fa9190600401615b16565b60405180910390fd5b6000826001600160a01b031663bd02d0f560405160200161074c9060208082526014908201527309a82b0bea6ae82a0bea082a890be988a9c8ea8960631b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161078091815260200190565b602060405180830381865afa15801561079d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c19190615a39565b905080825111156107ea57815181604051639da3604360e01b81526004016106fa929190615a2b565b60005b825181101561082757600083828151811061080a5761080a615a15565b6020026020010151905061081e8582611528565b506001016107ed565b50505050565b60005b81518110156105355761085c8383838151811061084f5761084f615a15565b602002602001015161053a565b600101610830565b600061086e6151ee565b600061087d8960000151610448565b905060006108908b8b8b8b8b8b8b610c6c565b9050816000036108ba576108af68327cb2734119d3b7a9601e1b6115b1565b935091506108f19050565b80516000036108d0576000935091506108f19050565b60006108e9670de0b6b3a764000083600001518561161f565b945090925050505b97509795505050505050565b600061090e88888888888888611668565b905061091c888888846116af565b505050505050505050565b6000806109348584611736565b91509150816000146109cb5761095d85858561094f866115b1565b61095890615b40565b6118cc565b604051633a5d319360e21b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063e974c64c9061099a908790879087908790600401615b5c565b60006040518083038186803b1580156109b257600080fd5b505af41580156109c6573d6000803e3d6000fd5b505050505b846001600160a01b031663e2a4853a6109e385611f67565b426040518363ffffffff1660e01b8152600401610a01929190615a2b565b6020604051808303816000875af1158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190615a39565b505050505050565b6000610a59858484611fb6565b9050610a7e858585600001518660400151600186606001516000015160000151612359565b610aa1858585600001518660400151600086606001516020015160000151612359565b610ac4858585600001518660600151600186606001516000015160200151612359565b610ae7858585600001518660600151600086606001516020015160200151612359565b8251604084015160808301515151610b05928892889260019061241f565b610b2885858560000151866040015160008660800151602001516000015161241f565b610b4b85858560000151866060015160018660800151600001516020015161241f565b610b6e85858560000151866060015160008660800151602001516020015161241f565b610b8185846000015183604001516124e6565b50846001600160a01b031663e2a4853a610b9e8560000151612561565b426040518363ffffffff1660e01b8152600401610bbc929190615a2b565b6020604051808303816000875af1158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190615a39565b508251602082015160405163387a0f1360e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9263387a0f1392610c409289929190600401615a52565b60006040518083038186803b158015610c5857600080fd5b505af415801561091c573d6000803e3d6000fd5b610c746151ee565b610c7c6151ee565b610c8b89898a60400151612599565b60808201526060880151610ca2908a908a90612599565b60a0820152610cb18684612637565b8160800151610cc09190615b85565b60c0820152610ccf8584612637565b8160a00151610cde9190615b85565b60e0820181905260c0820151610cfc91610cf791615b9c565b6115b1565b81526040805160608101825288815260208101889052908101869052610d258a8a83600161264e565b610100830152610d388a8a83600061264e565b8261010001818151610d4a9190615b9c565b9052506040516001600160a01b038b169063bd02d0f590610d9f906020016020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dd391815260200190565b602060405180830381865afa158015610df0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e149190615a39565b610e2a9068327cb2734119d3b7a9601e1b615baf565b6101208301819052610100830151610e4691610cf791906126a4565b82518390610e55908390615bc2565b905250610e678a8a8a600188156126bd565b60208301819052895160c0840151610e86928d9291600191908a612749565b6020830152610e9a8a8a8a600088156126bd565b60408301819052895160e0840151610eb9928d9291600091908a612749565b604083018190526020830151610ecf9190615bc2565b606083018190528251610ee29190615bea565b82528851610ef1908b90612799565b6101408301526000610f04898615612637565b836101400151610f149190615b85565b9050610f1f816115b1565b83518490610f2e908390615bea565b90525089516001600160a01b038c169063bd02d0f590610f4d906127a6565b6040518263ffffffff1660e01b8152600401610f6b91815260200190565b602060405180830381865afa158015610f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fac9190615a39565b6101608401526000610fbe8a87612637565b846101600151610fce9190615b85565b9050610fd9816115b1565b84518590610fe8908390615bc2565b905250929b9a5050505050505050505050565b6110036151c7565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff59061103f9087908790600401615a76565b608060405180830381865af415801561105c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110809190615a90565b905061062a84826127e7565b6000806000806110a18888600001518761282e565b905060006110b18989898961285a565b905060006110c48a8a6000015189612a7a565b905060006110d28385615b85565b905060006110e08284615b9c565b9c919b50929950975050505050505050565b6000856001600160a01b031663340dbab361110d8686612ad0565b846040518363ffffffff1660e01b815260040161112b929190615a2b565b6020604051808303816000875af115801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e9190615a39565b60405163d206b70560e01b81526001600160a01b038088166004830152861660248201528415156044820152606481018490526084810182905290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063d206b7059060a40160006040518083038186803b1580156111e257600080fd5b505af41580156111f6573d6000803e3d6000fd5b50505050505050505050565b60006040516020016112549060208082526026908201527f43554d554c41544956455f424f52524f57494e475f464143544f525f5550444160408201526515115117d05560d21b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0385169082015282151560608201526080015b60405160208183030381529060405280519060200120905092915050565b81516001600160a01b031615806112c657506001600160a01b038116155b156112e957815160405163e474a42560e01b81526106fa91908390600401615a76565b81516040516370a0823160e01b81526000916001600160a01b038416916370a082319161131891600401615b16565b602060405180830381865afa158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190615a39565b90506000611368858585612b11565b9050808210156113945783516040516333a1ea6b60e01b81526106fa9190859085908590600401615b5c565b60006113a886866000015186600180612e2b565b90506113bd8686600001518660006001612e2b565b6113c79082615b9c565b9050808310156113f357845160405163808c464f60e01b81526106fa9190869086908590600401615b5c565b6000866001600160a01b031663bd02d0f5611412886000015188612eb1565b6040518263ffffffff1660e01b815260040161143091815260200190565b602060405180830381865afa15801561144d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114719190615a39565b90508084101561149d578551604051639dd026db60e01b81526106fa9190879087908590600401615b5c565b50505050505050565b60006040516020016114de906020808252601290820152711254d7d3505492d15517d11254d05093115160721b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906115649086908690600401615a76565b608060405180830381865af4158015611581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a59190615a90565b905061053583826127e7565b60006001600160ff1b0382111561161b5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016106fa565b5090565b6000806116358561162f86612f2c565b85612f3f565b90506000841361165657611648816115b1565b61165190615b40565b61165f565b61165f816115b1565b95945050505050565b600080611676898989612f4c565b905061168286866126a4565b61168c9082615baf565b905061169884846126a4565b6116a29082615b9c565b9998505050505050505050565b6000846001600160a01b031663e2a4853a6116ca8686612f63565b846040518363ffffffff1660e01b81526004016116e8929190615a2b565b6020604051808303816000875af1158015611707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172b9190615a39565b90505b949350505050565b60008060006117458585612f98565b90508060000361175a576000925090506118c5565b6000856001600160a01b031663bd02d0f561177487613011565b6040518263ffffffff1660e01b815260040161179291815260200190565b602060405180830381865afa1580156117af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d39190615a39565b9050806000036117e957506000925090506118c5565b6000866001600160a01b031663bd02d0f561180388613063565b6040518263ffffffff1660e01b815260040161182191815260200190565b602060405180830381865afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190615a39565b905080831161187a57600083945094505050506118c5565b60006118868285615baf565b9050600061189489896130a6565b905060006118a282866126a4565b9050828111156118af5750815b806118ba8188615baf565b975097505050505050505b9250929050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915261190782612f2c565b60408201526000821215611c625761191e8361313e565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b9190615a39565b6060820181905260408201511115611bac57806060015181604001516119b19190615baf565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a916119e69190600090600401615a2b565b6020604051808303816000875af1158015611a05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a299190615a39565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585611a5385606001516115b1565b60006040518563ffffffff1660e01b8152600401611a749493929190615b5c565b60006040518083038186803b158015611a8c57600080fd5b505af4158015611aa0573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611abc856127a6565b83608001516040518363ffffffff1660e01b8152600401611ade929190615a2b565b6020604051808303816000875af1158015611afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b219190615a39565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818585611b5385608001516115b1565b8560a001516040518563ffffffff1660e01b8152600401611b779493929190615b5c565b60006040518083038186803b158015611b8f57600080fd5b505af4158015611ba3573d6000803e3d6000fd5b50505050611f60565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611bdd92600401615a2b565b6020604051808303816000875af1158015611bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c209190615a39565b60a0820181905260405163555a997960e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9163555a997991611b7791889188918891600401615b5c565b611c6b836127a6565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611cb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdc9190615a39565b6060820181905260408201511115611ea75780606001518160400151611d029190615baf565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a91611d3a9190600090600401615a2b565b6020604051808303816000875af1158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d9190615a39565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818585611da785606001516115b1565b60006040518563ffffffff1660e01b8152600401611dc89493929190615b5c565b60006040518083038186803b158015611de057600080fd5b505af4158015611df4573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611e108561313e565b83608001516040518363ffffffff1660e01b8152600401611e32929190615a2b565b6020604051808303816000875af1158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190615a39565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585611b5385608001516115b1565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611edb92600401615a2b565b6020604051808303816000875af1158015611efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1e9190615a39565b60a08201819052604051634ddb3d8160e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__91634ddb3d8191610c4091889188918891600401615b5c565b5050505050565b60006040516020016114de9060208082526023908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554454460408201526217d05560ea1b606082015260800190565b611fbe61524f565b611fc661524f565b611fce61528b565b6000611fe28660400151876060015161317f565b9050611ffa87876000015188604001516001856131ae565b82515152855160608701516120139189916001856131ae565b825151602001528551604087015161202f9189916000856131ae565b825160200151528551606087015161204b9189916000856131ae565b825160209081015181019190915282515190810151905161206c9190615b9c565b602080840191909152825181015190810151905161208a9190615b9c565b6040830152602082015115806120a257506040820151155b156120b25782935050505061062a565b6120c08787600001516131cb565b606083018190528651602084015160408501516120e1938b939291906131e6565b604086015215158085526020850191909152612101578160400151612107565b81602001515b608083018190526020840151606084015161212b929161212691615b85565b6126a4565b60a0830181905261213d908290615c27565b60a083015282511561218e5760a0820151825151516020840151612162929190612f3f565b60c083015260a082015182515160209081015190840151612184929190612f3f565b60e08301526121d4565b60a08201518251602001515160408401516121aa929190612f3f565b60c083015260a08201518251602090810151015160408401516121ce929190612f3f565b60e08301525b8251156122925760c08201518251515160208088015101516121f992919060016138ef565b6060840151515260e082015182515160209081015160408801519091015161222492919060016138ef565b83606001516000015160200181815250506122528260c00151836040015187602001516020015160006138ef565b83608001516020015160000181815250506122808260e00151836040015187604001516020015160006138ef565b6080840151602090810151015261234e565b6122b78260c001518360000151602001516000015187602001516020015160016138ef565b83606001516020015160000181815250506122ed8260e001518360000151602001516020015187604001516020015160016138ef565b836060015160200151602001818152505061231b8260c00151836020015187602001516020015160006138ef565b6080840151515260e082015160208084015160408801519091015161234392919060006138ef565b608084015151602001525b509095945050505050565b8015610a44576000866001600160a01b0316633dbacd1a61237b878787613957565b846040518363ffffffff1660e01b8152600401612399929190615a2b565b6020604051808303816000875af11580156123b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dc9190615a39565b6040516261034760e41b815290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063061034709061040f90899089908990899089908990600401615c3b565b8015610a44576000866001600160a01b0316633dbacd1a6124418787876139f8565b846040518363ffffffff1660e01b815260040161245f929190615a2b565b6020604051808303816000875af115801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a29190615a39565b604051636d6b205960e01b815290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__90636d6b20599061040f90899089908990899089908990600401615c3b565b6000836001600160a01b0316633e49bed061250085613a45565b846040518363ffffffff1660e01b815260040161251e929190615a2b565b6020604051808303816000875af115801561253d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190615a39565b60006040516020016114de9060208082526012908201527111955391125391d7d554111055115117d05560721b604082015260600190565b6000806125ae8460400151856060015161317f565b905080856001600160a01b031663bd02d0f56125ce876000015187613a88565b6040518263ffffffff1660e01b81526004016125ec91815260200190565b602060405180830381865afa158015612609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262d9190615a39565b61165f9190615c27565b60008161264557825161062a565b50506020015190565b60008061265c868685613ab9565b9050600061266c8787878761108c565b50509050600061268188886000015187612f4c565b90508061268e84846126a4565b6126989190615baf565b98975050505050505050565b600061062a838368327cb2734119d3b7a9601e1b612f3f565b6000806126ce610cf7888887613ab9565b905060006126dd888887613b17565b90508115806126ea575080155b156126fa5760009250505061165f565b6000612707878787613b5e565b90506000612718610cf78385615b85565b90506000876127305761272b8286615bea565b61273a565b61273a8583615bea565b9b9a5050505050505050505050565b60008084121561275a57508261278f565b600061276888848989613b97565b90506000612779610cf786846126a4565b9050808613612788578561278a565b805b925050505b9695505050505050565b60008061165f8484611736565b60006040516020016114de906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b6127f18282610631565b80606001516001600160a01b031681604001516001600160a01b03160361057d5780516040516332e6f44d60e21b81526106fa9190600401615b16565b60008061283c858585613bee565b90508060000361285057600091505061062a565b61165f8142615baf565b60008061286986868686613c09565b90508060000361287d57600091505061172e565b6000866001600160a01b0316637ae1cfca6040516020016128db9060208082526023908201527f534b49505f424f52524f57494e475f4645455f464f525f534d414c4c45525f5360408201526249444560e81b606082015260800190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161290f91815260200190565b602060405180830381865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129509190615af9565b905080156129b857600061296688886001613ab9565b9050600061297689896000613ab9565b905085801561298457508082105b1561299657600094505050505061172e565b851580156129a357508181105b156129b557600094505050505061172e565b50505b60006129c8888888886000613c45565b9050806000036129eb57604051630d5f5aef60e31b815260040160405180910390fd5b60006129fc89896000015188613cbe565b90508015612a1d57612a12898988878686613cd9565b94505050505061172e565b6000612a2e8a8a6000015189613e88565b90506000612a3c8683613ea3565b90506000612a4a8286613f02565b90506000612a5d8d8d600001518c613f10565b9050612a6982826126a4565b9d9c50505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a958585612ad0565b6040518263ffffffff1660e01b8152600401612ab391815260200190565b602060405180830381865afa15801561253d573d6000803e3d6000fd5b6000604051602001611254906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b6000612b4c6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b846001600160a01b031663bd02d0f5612b69866000015186613a88565b6040518263ffffffff1660e01b8152600401612b8791815260200190565b602060405180830381865afa158015612ba4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc89190615a39565b81528351612bd890869085613f2b565b602082015283516001600160a01b0386169063bd02d0f590612bfa9086613f46565b6040518263ffffffff1660e01b8152600401612c1891815260200190565b602060405180830381865afa158015612c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c599190615a39565b604082015283516001600160a01b0386169063bd02d0f590612c7b9086613f87565b6040518263ffffffff1660e01b8152600401612c9991815260200190565b602060405180830381865afa158015612cb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cda9190615a39565b606082015283516001600160a01b0386169063bd02d0f590612cfc9086613fc1565b6040518263ffffffff1660e01b8152600401612d1a91815260200190565b602060405180830381865afa158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5b9190615a39565b608082015283516001600160a01b0386169063bd02d0f590612d7d9086613ffe565b6040518263ffffffff1660e01b8152600401612d9b91815260200190565b602060405180830381865afa158015612db8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddc9190615a39565b60a0820181905260808201516060830151604084015160208501518551612e039190615b9c565b612e0d9190615b9c565b612e179190615b9c565b612e219190615b9c565b61165f9190615b9c565b600081866001600160a01b031663bd02d0f5612e48888888614034565b6040518263ffffffff1660e01b8152600401612e6691815260200190565b602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea79190615a39565b61278f9190615c27565b6000604051602001612eef9060208082526018908201527710d31052535050931157d1955391125391d7d05353d5539560421b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800161128a565b60008082121561161b578160000361032a565b600061172e848484614068565b6000836001600160a01b031663bd02d0f5612a9585855b6000604051602001611254906020808252600f908201526e544f54414c5f424f52524f57494e4760881b604082015260600190565b6000826001600160a01b031663bd02d0f5612fb28461313e565b6040518263ffffffff1660e01b8152600401612fd091815260200190565b602060405180830381865afa158015612fed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062a9190615a39565b60006040516020016114de9060208082526026908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554494f6040820152654e5f5241544560d01b606082015260800190565b60006040516020016114de906020808252601f908201527f4d494e5f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e5400604082015260600190565b600080836001600160a01b031663bd02d0f56130c185611f67565b6040518263ffffffff1660e01b81526004016130df91815260200190565b602060405180830381865afa1580156130fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131209190615a39565b90508060000361313457600091505061032a565b61172e8142615baf565b60006040516020016114de906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000816001600160a01b0316836001600160a01b0316146131a15760016131a4565b60025b60ff169392505050565b600081866001600160a01b031663bd02d0f5612e48888888614152565b600080836001600160a01b031663bd02d0f56130c185612561565b6000806000613241604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61324b8787614185565b81526132578688615b9c565b8160200181815250506132996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b896001600160a01b031663bd02d0f56132b18b6141a7565b6040518263ffffffff1660e01b81526004016132cf91815260200190565b602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190615a39565b6040820152815115801561332657506040810151155b1561333e5760006001600094509450945050506138e4565b8160200151600003613363576040516311423d9560e01b815260040160405180910390fd5b61336d8a8a6141f5565b60608301819052825161337f91613ea3565b6080830181905260208301516133959190613f02565b60a08301526040810151600003613465576133b08a8a61420f565b604083015260006001600160a01b038b1663bd02d0f56133cf8c614229565b6040518263ffffffff1660e01b81526004016133ed91815260200190565b602060405180830381865afa15801561340a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342e9190615a39565b905060006134448460a0015185604001516126a4565b9050818111156134515750805b955050508587119250600091506138e49050565b61346f8a8a61426c565b60c0830181905261347f90612f2c565b60e08301526001600160a01b038a1663bd02d0f561349c8b614286565b6040518263ffffffff1660e01b81526004016134ba91815260200190565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb9190615a39565b81526001600160a01b038a1663bd02d0f56135158b6142c8565b6040518263ffffffff1660e01b815260040161353391815260200190565b602060405180830381865afa158015613550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135749190615a39565b602082015260c082015161010083018190526000908190811280156135985750888a115b806135b1575060008460c001511280156135b157508989115b905080156135e957825160a085015111156135cf57600191506135ee565b82602001518460a0015110156135e457600291505b6135ee565b600191505b600182600281111561360257613602615c76565b0361365f576000613612896115b1565b613627610cf78760a0015187604001516126a4565b6136319190615c8c565b9050898b10156136475761364481615b40565b90505b808560c001516136579190615bc2565b610100860152505b600282600281111561367357613673615c76565b148015613683575060e084015115155b15613790578b6001600160a01b031663bd02d0f56136a08d61430b565b6040518263ffffffff1660e01b81526004016136be91815260200190565b602060405180830381865afa1580156136db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ff9190615a39565b60608401819052600090613714908a90615b85565b9050808560e00151116137485761372e8560e001516115b1565b8560c0015161373d9190615cbc565b61010086015261378e565b60006137578660e001516115b1565b8660c001516137669190615cbc565b90508061377c838860e00151610cf79190615baf565b6137869190615c8c565b610100870152505b505b8b6001600160a01b031663bd02d0f56137a88d614359565b6040518263ffffffff1660e01b81526004016137c691815260200190565b602060405180830381865afa1580156137e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138079190615a39565b60808401526001600160a01b038c1663bd02d0f56138248d614229565b6040518263ffffffff1660e01b815260040161384291815260200190565b602060405180830381865afa15801561385f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138839190615a39565b60a0840181905261010085015161389c9160009061439c565b6101008501819052608084015160a08501516138b992919061439c565b61012085018190526138ca90612f2c565b600085610120015113856101000151965096509650505050505b955095509592505050565b60008415806138fc575083155b156139095750600061172e565b60006139338661392c66038d7ea4c6800068327cb2734119d3b7a9601e1b615b85565b87866143fc565b9050821561394d576139458185614423565b91505061172e565b6139458482615c27565b6000604051602001613998906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016139989060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b60006040516020016114de906020808252601f908201527f53415645445f46554e44494e475f464143544f525f5045525f5345434f4e4400604082015260600190565b6000604051602001612eef906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b600080613ace8460400151856060015161317f565b90506000613ae7868660000151876040015187866131ae565b90506000613b00878760000151886060015188876131ae565b9050613b0c8183615b9c565b979650505050505050565b600080613b2c8460400151856060015161317f565b90506000613b4586866000015187604001518786614446565b90506000613b0087876000015188606001518887614446565b60008215613b7f5781613b72578351613b78565b83602001515b905061062a565b81613b8e57836020015161172e565b50509051919050565b6000846001600160a01b031663bd02d0f5613bb3868686614463565b6040518263ffffffff1660e01b8152600401613bd191815260200190565b602060405180830381865afa158015611707573d6000803e3d6000fd5b6000836001600160a01b031663bd02d0f5612a958585611202565b6000808215613c3a576000613c1f878786613b17565b855160200151909150613c329082615b85565b91505061172b565b61278f868685613ab9565b60008083613c57578560600151613c5d565b85604001515b90506000613c6c888884612599565b905060008415613c9a5785613c8957866040015160200151613c93565b8660200151602001515b9050613cb4565b85613caa57604087015151613cb1565b6020870151515b90505b6116a28183615b85565b6000836001600160a01b031663bd02d0f5612a9585856144d7565b600080613ce98888888888614511565b90506000886001600160a01b031663bd02d0f5613d0a8a600001518a61453f565b6040518263ffffffff1660e01b8152600401613d2891815260200190565b602060405180830381865afa158015613d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d699190615a39565b90506000613d7783836126a4565b90508483118015613d9357508468327cb2734119d3b7a9601e1b115b1561278a576000613da48685615baf565b905060008b6001600160a01b031663bd02d0f5613dc58d600001518d61457a565b6040518263ffffffff1660e01b8152600401613de391815260200190565b602060405180830381865afa158015613e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e249190615a39565b9050600084821115613e3d57613e3a8583615baf565b90505b6000613e558968327cb2734119d3b7a9601e1b615baf565b905080613e628584615b85565b613e6c9190615c27565b613e769086615b9c565b9e9d5050505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a9585856145ca565b600068327cb2734119d3b7a9601e1b831015613ec15750600061032a565b68327cb2734119d3b7a9601e1b8203613edb57508161032a565b6000613ef7613ee985614609565b613ef285614609565b61461a565b905061172e8161465c565b600061062a8383600061466d565b6000836001600160a01b031663bd02d0f5612a9585856146b5565b6000836001600160a01b031663bd02d0f5612a9585856146eb565b6000604051602001612eef906020808252601b908201527a10d31052535050931157d0d3d31310551154905317d05353d55395602a1b604082015260600190565b6000604051602001612eef9060208082526014908201527310d31052535050931157d1915157d05353d5539560621b604082015260600190565b6000604051602001612eef9060208082526017908201527610d31052535050931157d55257d1915157d05353d55395604a1b604082015260600190565b6000604051602001612eef9060208082526010908201526f10519192531250551157d49155d0549160821b604082015260600190565b6000604051602001613998906020808252600e908201526d434f4c4c41544552414c5f53554d60901b604082015260600190565b60008080600019858709858702925082811083820303915050806000036140a25783828161409857614098615c11565b049250505061062a565b8084116140e95760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016106fa565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001613998906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b600081831161419d576141988383615baf565b61062a565b61062a8284615baf565b60006040516020016114de9060208082526022908201527f46554e44494e475f494e4352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b6000826001600160a01b031663bd02d0f5612fb284614728565b6000826001600160a01b031663bd02d0f5612fb284614765565b60006040516020016114de906020808252601d908201527f4d41585f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000826001600160a01b031663dc97d962612fb284613a45565b60006040516020016114de906020808252601c908201527b5448524553484f4c445f464f525f535441424c455f46554e44494e4760201b604082015260600190565b60006040516020016114de906020808252601e908201527f5448524553484f4c445f464f525f44454352454153455f46554e44494e470000604082015260600190565b60006040516020016114de9060208082526022908201527f46554e44494e475f44454352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b60006040516020016114de906020808252601d908201527f4d494e5f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000806143a885612f2c565b9050838110156143b55750825b828111156143c05750815b600085156143e3576143d4610cf787612f2c565b6143de9087615cbc565b6143e6565b60015b9050806143f2836115b1565b61278f9190615c8c565b60008115614418576144118585856001614799565b905061172e565b61172b858585614068565b60008160016144328286615b9c565b61443c9190615baf565b61062a9190615c27565b600081866001600160a01b031663bd02d0f5612e488888886147ea565b6000604051602001614497906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a0016139d9565b60006040516020016112549060208082526014908201527327a82a24a6a0a62faaa9a0a3a2afa320a1aa27a960611b604082015260600190565b60008061452387876000015187614827565b9050600061453184836126a4565b905060006116a28683613f02565b6000604051602001611254906020808252601590820152742120a9a2afa127a92927aba4a723afa320a1aa27a960591b604082015260600190565b60006040516020016112549060208082526024908201527f41424f56455f4f5054494d414c5f55534147455f424f52524f57494e475f464160408201526321aa27a960e11b606082015260800190565b6000604051602001611254906020808252601990820152782127a92927aba4a723afa2ac2827a722a72a2fa320a1aa27a960391b604082015260600190565b600061032a64e8d4a5100083615c27565b60008260000361464257811561463157600061463b565b670de0b6b3a76400005b905061032a565b61062a61465761465185614842565b846148f8565b614904565b600061032a64e8d4a5100083615b85565b60008360000361467f5750600061062a565b811561469e57613b788468327cb2734119d3b7a9601e1b856001614799565b61172e8468327cb2734119d3b7a9601e1b85614068565b60006040516020016112549060208082526010908201526f2127a92927aba4a723afa320a1aa27a960811b604082015260600190565b6000604051602001612eef9060208082526017908201527614d5d05417d253541050d517d413d3d317d05353d55395604a1b604082015260600190565b60006040516020016114de90602080825260179082015276232aa72224a723afa2ac2827a722a72a2fa320a1aa27a960491b604082015260600190565b60006040516020016114de906020808252600e908201526d232aa72224a723afa320a1aa27a960911b604082015260600190565b6000806147a7868686614068565b905060018360028111156147bd576147bd615c76565b1480156147da5750600084806147d5576147d5615c11565b868809115b1561172b5761278f600182615b9c565b6000604051602001613998906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b6000836001600160a01b031663bd02d0f5612a95858561494a565b6000670de0b6b3a764000082101561487057604051633621413760e21b8152600481018390526024016106fa565b6000614885670de0b6b3a7640000840461498c565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff1981016148ae575050919050565b6706f05b59d3b200005b80156148f057670de0b6b3a7640000828002049150671bc16d674ec8000082106148e8579283019260019190911c905b60011c6148b8565b505050919050565b600061062a8383614a6f565b6000680a688906bd8b000000821061493257604051634a4f26f160e01b8152600481018390526024016106fa565b670de0b6b3a7640000604083901b0461062a81614b35565b6000604051602001611254906020808252601c908201527b27a822a72fa4a72a22a922a9aa2fa922a9a2a92b22afa320a1aa27a960211b604082015260600190565b6000600160801b82106149ac57608091821c916149a99082615b9c565b90505b600160401b82106149ca57604091821c916149c79082615b9c565b90505b600160201b82106149e857602091821c916149e59082615b9c565b90505b620100008210614a0557601091821c91614a029082615b9c565b90505b6101008210614a2157600891821c91614a1e9082615b9c565b90505b60108210614a3c57600491821c91614a399082615b9c565b90505b60048210614a5757600291821c91614a549082615b9c565b90505b60028210614a6a5761032a600182615b9c565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110614ab35760405163698d9a0160e11b8152600481018290526024016106fa565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff8211905082600003614af15780670de0b6b3a764000085040194505050505061032a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b821615614b555768016a09e667f3bcc9090260401c5b6001603e1b821615614b70576801306fe0a31b7152df0260401c5b6001603d1b821615614b8b576801172b83c7d517adce0260401c5b6001603c1b821615614ba65768010b5586cf9890f62a0260401c5b6001603b1b821615614bc1576801059b0d31585743ae0260401c5b6001603a1b821615614bdc57680102c9a3e778060ee70260401c5b600160391b821615614bf75768010163da9fb33356d80260401c5b600160381b821615614c1257680100b1afa5abcbed610260401c5b600160371b821615614c2d5768010058c86da1c09ea20260401c5b600160361b821615614c48576801002c605e2e8cec500260401c5b600160351b821615614c6357680100162f3904051fa10260401c5b600160341b821615614c7e576801000b175effdc76ba0260401c5b600160331b821615614c9957680100058ba01fb9f96d0260401c5b600160321b821615614cb45768010002c5cc37da94920260401c5b600160311b821615614ccf576801000162e525ee05470260401c5b600160301b821615614cea5768010000b17255775c040260401c5b6001602f1b821615614d05576801000058b91b5bc9ae0260401c5b6001602e1b821615614d2057680100002c5c89d5ec6d0260401c5b6001602d1b821615614d3b5768010000162e43f4f8310260401c5b6001602c1b821615614d5657680100000b1721bcfc9a0260401c5b6001602b1b821615614d715768010000058b90cf1e6e0260401c5b6001602a1b821615614d8c576801000002c5c863b73f0260401c5b600160291b821615614da757680100000162e430e5a20260401c5b600160281b821615614dc2576801000000b1721835510260401c5b600160271b821615614ddd57680100000058b90c0b490260401c5b600160261b821615614df85768010000002c5c8601cc0260401c5b600160251b821615614e13576801000000162e42fff00260401c5b600160241b821615614e2e5768010000000b17217fbb0260401c5b600160231b821615614e49576801000000058b90bfce0260401c5b600160221b821615614e6457680100000002c5c85fe30260401c5b600160211b821615614e7f5768010000000162e42ff10260401c5b600160201b821615614e9a57680100000000b17217f80260401c5b6380000000821615614eb55768010000000058b90bfc0260401c5b6340000000821615614ed0576801000000002c5c85fe0260401c5b6320000000821615614eeb57680100000000162e42ff0260401c5b6310000000821615614f06576801000000000b17217f0260401c5b6308000000821615614f2157680100000000058b90c00260401c5b6304000000821615614f3c5768010000000002c5c8600260401c5b6302000000821615614f57576801000000000162e4300260401c5b6301000000821615614f725768010000000000b172180260401c5b62800000821615614f8c576801000000000058b90c0260401c5b62400000821615614fa657680100000000002c5c860260401c5b62200000821615614fc05768010000000000162e430260401c5b62100000821615614fda57680100000000000b17210260401c5b62080000821615614ff45768010000000000058b910260401c5b6204000082161561500e576801000000000002c5c80260401c5b6202000082161561502857680100000000000162e40260401c5b620100008216156150415761b172600160401b010260401c5b618000821615615059576158b9600160401b010260401c5b61400082161561507157612c5d600160401b010260401c5b6120008216156150895761162e600160401b010260401c5b6110008216156150a157610b17600160401b010260401c5b6108008216156150b95761058c600160401b010260401c5b6104008216156150d1576102c6600160401b010260401c5b6102008216156150e957610163600160401b010260401c5b6101008216156151005760b1600160401b010260401c5b6080821615615116576059600160401b010260401c5b604082161561512c57602c600160401b010260401c5b6020821615615142576016600160401b010260401c5b601082161561515857600b600160401b010260401c5b600882161561516e576006600160401b010260401c5b6004821615615184576003600160401b010260401c5b600282161561519a576001600160401b010260401c5b60018216156151b0576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060001515815260200160008152602001600081526020016152796152d6565b81526020016152866152d6565b905290565b60405180610100016040528061529f6152d6565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60408051608081018252600091810182815260608201929092529081908152602001615286604051806040016040528060008152602001600081525090565b6001600160a01b038116811461532a57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156153655761536561532d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156153935761539361532d565b604052919050565b60006001600160401b038211156153b4576153b461532d565b5060051b60200190565b600080604083850312156153d157600080fd5b82356153dc81615315565b915060208301356001600160401b038111156153f757600080fd5b8301601f8101851361540857600080fd5b803561541b6154168261539b565b61536b565b8082825260208201915060208360051b85010192508783111561543d57600080fd5b6020840193505b8284101561546857833561545781615315565b825260209384019390910190615444565b809450505050509250929050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b602080825282518282018190526000918401906040840190835b8181101561234e576154d6838551615476565b60209390930192608092909201916001016154c3565b6000608082840312156154fe57600080fd5b615506615343565b9050813561551381615315565b8152602082013561552381615315565b6020820152604082013561553681615315565b6040820152606082013561554981615315565b606082015292915050565b60006040828403121561556657600080fd5b604080519081016001600160401b03811182821017156155885761558861532d565b604052823581526020928301359281019290925250919050565b600060c082840312156155b457600080fd5b604051606081016001600160401b03811182821017156155d6576155d661532d565b6040529050806155e68484615554565b81526155f58460408501615554565b60208201526156078460808501615554565b60408201525092915050565b801515811461532a57600080fd5b60008060008060006101a0868803121561563a57600080fd5b853561564581615315565b9450602086013561565581615315565b935061566487604088016154ec565b92506156738760c088016155a2565b915061018086013561568481615613565b809150509295509295909350565b6000602082840312156156a457600080fd5b813561062a81615315565b600080604083850312156156c257600080fd5b82356156cd81615315565b915060208301356156dd81615315565b809150509250929050565b60008060a083850312156156fb57600080fd5b823561570681615315565b915061571584602085016154ec565b90509250929050565b6080810161032a8284615476565b6000806040838503121561573f57600080fd5b823561574a81615315565b915060208301356001600160401b0381111561576557600080fd5b8301601f8101851361577657600080fd5b80356157846154168261539b565b8082825260208201915060208360071b8501019250878311156157a657600080fd5b6020840193505b82841015615468576157bf88856154ec565b82526020820191506080840193506157ad565b60008060008060008060006101a0888a0312156157ee57600080fd5b87356157f981615315565b96506158088960208a016154ec565b95506158178960a08a01615554565b94506158268960e08a01615554565b9350615836896101208a01615554565b9250610160880135915061018088013561584f81615613565b8091505092959891949750929550565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008101516101008301526101208101516101208301526101408101516101408301526101608101516101608301525050565b8281526101a0810161062a602083018461585f565b600080600080600080600060e0888a03121561590d57600080fd5b873561591881615315565b9650602088013561592881615315565b9550604088013561593881615613565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b60008060006060848603121561597557600080fd5b833561598081615315565b9250602084013561599081615315565b915060408401356159a081615315565b809150509250925092565b60008060008061018085870312156159c257600080fd5b84356159cd81615315565b935060208501356159dd81615315565b92506159ec86604087016154ec565b91506159fb8660c087016155a2565b905092959194509250565b610180810161032a828461585f565b634e487b7160e01b600052603260045260246000fd5b918252602082015260400190565b600060208284031215615a4b57600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0392831681529116602082015260400190565b60006080828403128015615aa357600080fd5b50615aac615343565b8251615ab781615315565b81526020830151615ac781615315565b60208201526040830151615ada81615315565b60408201526060830151615aed81615315565b60608201529392505050565b600060208284031215615b0b57600080fd5b815161062a81615613565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201615b5557615b55615b2a565b5060000390565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b808202811582820484141761032a5761032a615b2a565b8082018082111561032a5761032a615b2a565b8181038181111561032a5761032a615b2a565b8082018281126000831280158216821582161715615be257615be2615b2a565b505092915050565b8181036000831280158383131683831282161715615c0a57615c0a615b2a565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600082615c3657615c36615c11565b500490565b6001600160a01b039687168152948616602086015292909416604084015215156060830152608082019290925260a081019190915260c00190565b634e487b7160e01b600052602160045260246000fd5b80820260008212600160ff1b84141615615ca857615ca8615b2a565b818105831482151761032a5761032a615b2a565b600082615ccb57615ccb615c11565b600160ff1b821460001984141615615ce557615ce5615b2a565b50059056fea264697066735822122068c56c92b780c3694e90a9239b6e8532ace780972d05932a36bec2715eedb8b964736f6c634300081d0033", + "numDeployments": 25, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"DisabledMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"EmptyAddressInMarketTokenBalanceValidation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expectedMinBalance\",\"type\":\"uint256\"}],\"name\":\"InvalidMarketTokenBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"claimableFundingFeeAmount\",\"type\":\"uint256\"}],\"name\":\"InvalidMarketTokenBalanceForClaimableFunding\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"}],\"name\":\"InvalidMarketTokenBalanceForCollateralAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"InvalidSwapMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"swapPathLengh\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSwapPathLength\",\"type\":\"uint256\"}],\"name\":\"MaxSwapPathLengthExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__Exp2InputTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__LogInputTooSmall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivFixedPointOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnableToGetBorrowingFactorEmptyPoolUsd\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnableToGetFundingFactorEmptyOpenInterest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"marketAddress\",\"type\":\"address\"}],\"name\":\"getEnabledMarket\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"pnlFactorType\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"maximize\",\"type\":\"bool\"}],\"name\":\"getMarketTokenPrice\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"poolValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"longPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"shortPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"netPnl\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrowingFees\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFeePoolFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"impactPoolAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lentImpactPoolAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct MarketPoolValueInfo.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract MarketToken\",\"name\":\"marketToken\",\"type\":\"MarketToken\"}],\"name\":\"getMarketTokenSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"pnlFactorType\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"maximize\",\"type\":\"bool\"}],\"name\":\"getPoolValueInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"int256\",\"name\":\"poolValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"longPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"shortPnl\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"netPnl\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrowingFees\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFeePoolFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"impactPoolAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lentImpactPoolAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct MarketPoolValueInfo.Props\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"name\":\"getSwapPathMarkets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"marketAddress\",\"type\":\"address\"}],\"name\":\"validateEnabledMarket\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"}],\"name\":\"validateEnabledMarket\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"}],\"name\":\"validateMarketTokenBalance\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address\",\"name\":\"_market\",\"type\":\"address\"}],\"name\":\"validateMarketTokenBalance\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props[]\",\"name\":\"markets\",\"type\":\"tuple[]\"}],\"name\":\"validateMarketTokenBalance\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"name\":\"validateSwapPath\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMathUD60x18__Exp2InputTooBig(uint256)\":[{\"notice\":\"Emitted when the input is greater than 192.\"}],\"PRBMathUD60x18__LogInputTooSmall(uint256)\":[{\"notice\":\"Emitted when the input is less than 1.\"}],\"PRBMath__MulDivFixedPointOverflow(uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/MarketUtils.sol\":\"MarketUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x615d20610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100cf5760003560e01c80630988a8f7146100d45780631450a879146100fd57806316ba20891461011f5780631ded168e1461014057806339b1348f146101535780635930015e146101665780635d95a47e1461017957806361a6d817146101995780637b3435fc146101ac5780637b672c9a146101bf5780637d494dc3146101d2578063b656ff7a146101f3578063c468d13514610213578063d2ab7dc014610233578063f2e2a4f514610253575b600080fd5b6100e76100e23660046153be565b610273565b6040516100f491906154a9565b60405180910390f35b81801561010957600080fd5b5061011d610118366004615621565b610330565b005b61013261012d366004615692565b610448565b6040519081526020016100f4565b61011d61014e3660046156af565b6104ac565b61011d6101613660046156e8565b61053a565b61011d6101743660046156af565b610581565b61018c6101873660046156af565b610599565b6040516100f4919061571e565b61011d6101a73660046156e8565b610631565b61011d6101ba3660046153be565b610703565b61011d6101cd36600461572c565b61082d565b6101e56101e03660046157d2565b610864565b6040516100f49291906158dd565b8180156101ff57600080fd5b5061011d61020e3660046158f2565b6108fd565b81801561021f57600080fd5b5061011d61022e366004615960565b610927565b81801561023f57600080fd5b5061011d61024e3660046159ab565b610a4c565b6102666102613660046157d2565b610c6c565b6040516100f49190615a06565b6060600082516001600160401b038111156102905761029061532d565b6040519080825280602002602001820160405280156102c957816020015b6102b66151c7565b8152602001906001900390816102ae5790505b50905060005b83518110156103265760008482815181106102ec576102ec615a15565b602002602001015190506103008682610ffb565b83838151811061031257610312615a15565b6020908102919091010152506001016102cf565b5090505b92915050565b60008061033f8786868661108c565b92509250506103558787876000015186866110f2565b866001600160a01b031663e2a4853a610372876000015186611202565b426040518363ffffffff1660e01b8152600401610390929190615a2b565b6020604051808303816000875af11580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d39190615a39565b508451604051635375a20760e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c891635375a2079161040f918a918690600401615a52565b60006040518083038186803b15801561042757600080fd5b505af415801561043b573d6000803e3d6000fd5b5050505050505050505050565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032a9190615a39565b60405163a8d8fff560e01b8152600090732e5D10A48C00cFcc6A31af873118d739323Ff71B9063a8d8fff5906104e89086908690600401615a76565b608060405180830381865af4158015610505573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105299190615a90565b90506105358382610631565b505050565b610549828283604001516112a8565b80606001516001600160a01b031681604001516001600160a01b03160361056e575050565b61057d828283606001516112a8565b5050565b600061058d8383610599565b9050610535838261053a565b6105a16151c7565b60405163a8d8fff560e01b8152600090732e5D10A48C00cFcc6A31af873118d739323Ff71B9063a8d8fff5906105dd9087908790600401615a76565b608060405180830381865af41580156105fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061e9190615a90565b905061062a8482610631565b9392505050565b80516001600160a01b0316610659576040516302fde0d760e11b815260040160405180910390fd5b6000826001600160a01b0316637ae1cfca61067784600001516114a6565b6040518263ffffffff1660e01b815260040161069591815260200190565b602060405180830381865afa1580156106b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d69190615af9565b905080156105355781516040516309f8c93760e01b81526106fa9190600401615b16565b60405180910390fd5b6000826001600160a01b031663bd02d0f560405160200161074c9060208082526014908201527309a82b0bea6ae82a0bea082a890be988a9c8ea8960631b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161078091815260200190565b602060405180830381865afa15801561079d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c19190615a39565b905080825111156107ea57815181604051639da3604360e01b81526004016106fa929190615a2b565b60005b825181101561082757600083828151811061080a5761080a615a15565b6020026020010151905061081e8582611528565b506001016107ed565b50505050565b60005b81518110156105355761085c8383838151811061084f5761084f615a15565b602002602001015161053a565b600101610830565b600061086e6151ee565b600061087d8960000151610448565b905060006108908b8b8b8b8b8b8b610c6c565b9050816000036108ba576108af68327cb2734119d3b7a9601e1b6115b1565b935091506108f19050565b80516000036108d0576000935091506108f19050565b60006108e9670de0b6b3a764000083600001518561161f565b945090925050505b97509795505050505050565b600061090e88888888888888611668565b905061091c888888846116af565b505050505050505050565b6000806109348584611736565b91509150816000146109cb5761095d85858561094f866115b1565b61095890615b40565b6118cc565b604051633a5d319360e21b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89063e974c64c9061099a908790879087908790600401615b5c565b60006040518083038186803b1580156109b257600080fd5b505af41580156109c6573d6000803e3d6000fd5b505050505b846001600160a01b031663e2a4853a6109e385611f67565b426040518363ffffffff1660e01b8152600401610a01929190615a2b565b6020604051808303816000875af1158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190615a39565b505050505050565b6000610a59858484611fb6565b9050610a7e858585600001518660400151600186606001516000015160000151612359565b610aa1858585600001518660400151600086606001516020015160000151612359565b610ac4858585600001518660600151600186606001516000015160200151612359565b610ae7858585600001518660600151600086606001516020015160200151612359565b8251604084015160808301515151610b05928892889260019061241f565b610b2885858560000151866040015160008660800151602001516000015161241f565b610b4b85858560000151866060015160018660800151600001516020015161241f565b610b6e85858560000151866060015160008660800151602001516020015161241f565b610b8185846000015183604001516124e6565b50846001600160a01b031663e2a4853a610b9e8560000151612561565b426040518363ffffffff1660e01b8152600401610bbc929190615a2b565b6020604051808303816000875af1158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190615a39565b508251602082015160405163387a0f1360e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89263387a0f1392610c409289929190600401615a52565b60006040518083038186803b158015610c5857600080fd5b505af415801561091c573d6000803e3d6000fd5b610c746151ee565b610c7c6151ee565b610c8b89898a60400151612599565b60808201526060880151610ca2908a908a90612599565b60a0820152610cb18684612637565b8160800151610cc09190615b85565b60c0820152610ccf8584612637565b8160a00151610cde9190615b85565b60e0820181905260c0820151610cfc91610cf791615b9c565b6115b1565b81526040805160608101825288815260208101889052908101869052610d258a8a83600161264e565b610100830152610d388a8a83600061264e565b8261010001818151610d4a9190615b9c565b9052506040516001600160a01b038b169063bd02d0f590610d9f906020016020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dd391815260200190565b602060405180830381865afa158015610df0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e149190615a39565b610e2a9068327cb2734119d3b7a9601e1b615baf565b6101208301819052610100830151610e4691610cf791906126a4565b82518390610e55908390615bc2565b905250610e678a8a8a600188156126bd565b60208301819052895160c0840151610e86928d9291600191908a612749565b6020830152610e9a8a8a8a600088156126bd565b60408301819052895160e0840151610eb9928d9291600091908a612749565b604083018190526020830151610ecf9190615bc2565b606083018190528251610ee29190615bea565b82528851610ef1908b90612799565b6101408301526000610f04898615612637565b836101400151610f149190615b85565b9050610f1f816115b1565b83518490610f2e908390615bea565b90525089516001600160a01b038c169063bd02d0f590610f4d906127a6565b6040518263ffffffff1660e01b8152600401610f6b91815260200190565b602060405180830381865afa158015610f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fac9190615a39565b6101608401526000610fbe8a87612637565b846101600151610fce9190615b85565b9050610fd9816115b1565b84518590610fe8908390615bc2565b905250929b9a5050505050505050505050565b6110036151c7565b60405163a8d8fff560e01b8152600090732e5D10A48C00cFcc6A31af873118d739323Ff71B9063a8d8fff59061103f9087908790600401615a76565b608060405180830381865af415801561105c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110809190615a90565b905061062a84826127e7565b6000806000806110a18888600001518761282e565b905060006110b18989898961285a565b905060006110c48a8a6000015189612a7a565b905060006110d28385615b85565b905060006110e08284615b9c565b9c919b50929950975050505050505050565b6000856001600160a01b031663340dbab361110d8686612ad0565b846040518363ffffffff1660e01b815260040161112b929190615a2b565b6020604051808303816000875af115801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e9190615a39565b60405163d206b70560e01b81526001600160a01b038088166004830152861660248201528415156044820152606481018490526084810182905290915073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89063d206b7059060a40160006040518083038186803b1580156111e257600080fd5b505af41580156111f6573d6000803e3d6000fd5b50505050505050505050565b60006040516020016112549060208082526026908201527f43554d554c41544956455f424f52524f57494e475f464143544f525f5550444160408201526515115117d05560d21b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0385169082015282151560608201526080015b60405160208183030381529060405280519060200120905092915050565b81516001600160a01b031615806112c657506001600160a01b038116155b156112e957815160405163e474a42560e01b81526106fa91908390600401615a76565b81516040516370a0823160e01b81526000916001600160a01b038416916370a082319161131891600401615b16565b602060405180830381865afa158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190615a39565b90506000611368858585612b11565b9050808210156113945783516040516333a1ea6b60e01b81526106fa9190859085908590600401615b5c565b60006113a886866000015186600180612e2b565b90506113bd8686600001518660006001612e2b565b6113c79082615b9c565b9050808310156113f357845160405163808c464f60e01b81526106fa9190869086908590600401615b5c565b6000866001600160a01b031663bd02d0f5611412886000015188612eb1565b6040518263ffffffff1660e01b815260040161143091815260200190565b602060405180830381865afa15801561144d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114719190615a39565b90508084101561149d578551604051639dd026db60e01b81526106fa9190879087908590600401615b5c565b50505050505050565b60006040516020016114de906020808252601290820152711254d7d3505492d15517d11254d05093115160721b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60405163a8d8fff560e01b8152600090732e5D10A48C00cFcc6A31af873118d739323Ff71B9063a8d8fff5906115649086908690600401615a76565b608060405180830381865af4158015611581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a59190615a90565b905061053583826127e7565b60006001600160ff1b0382111561161b5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016106fa565b5090565b6000806116358561162f86612f2c565b85612f3f565b90506000841361165657611648816115b1565b61165190615b40565b61165f565b61165f816115b1565b95945050505050565b600080611676898989612f4c565b905061168286866126a4565b61168c9082615baf565b905061169884846126a4565b6116a29082615b9c565b9998505050505050505050565b6000846001600160a01b031663e2a4853a6116ca8686612f63565b846040518363ffffffff1660e01b81526004016116e8929190615a2b565b6020604051808303816000875af1158015611707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172b9190615a39565b90505b949350505050565b60008060006117458585612f98565b90508060000361175a576000925090506118c5565b6000856001600160a01b031663bd02d0f561177487613011565b6040518263ffffffff1660e01b815260040161179291815260200190565b602060405180830381865afa1580156117af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d39190615a39565b9050806000036117e957506000925090506118c5565b6000866001600160a01b031663bd02d0f561180388613063565b6040518263ffffffff1660e01b815260040161182191815260200190565b602060405180830381865afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190615a39565b905080831161187a57600083945094505050506118c5565b60006118868285615baf565b9050600061189489896130a6565b905060006118a282866126a4565b9050828111156118af5750815b806118ba8188615baf565b975097505050505050505b9250929050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915261190782612f2c565b60408201526000821215611c625761191e8361313e565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b9190615a39565b6060820181905260408201511115611bac57806060015181604001516119b19190615baf565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a916119e69190600090600401615a2b565b6020604051808303816000875af1158015611a05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a299190615a39565b5073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c863555a99798585611a5385606001516115b1565b60006040518563ffffffff1660e01b8152600401611a749493929190615b5c565b60006040518083038186803b158015611a8c57600080fd5b505af4158015611aa0573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611abc856127a6565b83608001516040518363ffffffff1660e01b8152600401611ade929190615a2b565b6020604051808303816000875af1158015611afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b219190615a39565b8160a001818152505073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8634ddb3d818585611b5385608001516115b1565b8560a001516040518563ffffffff1660e01b8152600401611b779493929190615b5c565b60006040518083038186803b158015611b8f57600080fd5b505af4158015611ba3573d6000803e3d6000fd5b50505050611f60565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611bdd92600401615a2b565b6020604051808303816000875af1158015611bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c209190615a39565b60a0820181905260405163555a997960e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89163555a997991611b7791889188918891600401615b5c565b611c6b836127a6565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611cb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdc9190615a39565b6060820181905260408201511115611ea75780606001518160400151611d029190615baf565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a91611d3a9190600090600401615a2b565b6020604051808303816000875af1158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d9190615a39565b5073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8634ddb3d818585611da785606001516115b1565b60006040518563ffffffff1660e01b8152600401611dc89493929190615b5c565b60006040518083038186803b158015611de057600080fd5b505af4158015611df4573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611e108561313e565b83608001516040518363ffffffff1660e01b8152600401611e32929190615a2b565b6020604051808303816000875af1158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190615a39565b8160a001818152505073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c863555a99798585611b5385608001516115b1565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611edb92600401615a2b565b6020604051808303816000875af1158015611efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1e9190615a39565b60a08201819052604051634ddb3d8160e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c891634ddb3d8191610c4091889188918891600401615b5c565b5050505050565b60006040516020016114de9060208082526023908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554454460408201526217d05560ea1b606082015260800190565b611fbe61524f565b611fc661524f565b611fce61528b565b6000611fe28660400151876060015161317f565b9050611ffa87876000015188604001516001856131ae565b82515152855160608701516120139189916001856131ae565b825151602001528551604087015161202f9189916000856131ae565b825160200151528551606087015161204b9189916000856131ae565b825160209081015181019190915282515190810151905161206c9190615b9c565b602080840191909152825181015190810151905161208a9190615b9c565b6040830152602082015115806120a257506040820151155b156120b25782935050505061062a565b6120c08787600001516131cb565b606083018190528651602084015160408501516120e1938b939291906131e6565b604086015215158085526020850191909152612101578160400151612107565b81602001515b608083018190526020840151606084015161212b929161212691615b85565b6126a4565b60a0830181905261213d908290615c27565b60a083015282511561218e5760a0820151825151516020840151612162929190612f3f565b60c083015260a082015182515160209081015190840151612184929190612f3f565b60e08301526121d4565b60a08201518251602001515160408401516121aa929190612f3f565b60c083015260a08201518251602090810151015160408401516121ce929190612f3f565b60e08301525b8251156122925760c08201518251515160208088015101516121f992919060016138ef565b6060840151515260e082015182515160209081015160408801519091015161222492919060016138ef565b83606001516000015160200181815250506122528260c00151836040015187602001516020015160006138ef565b83608001516020015160000181815250506122808260e00151836040015187604001516020015160006138ef565b6080840151602090810151015261234e565b6122b78260c001518360000151602001516000015187602001516020015160016138ef565b83606001516020015160000181815250506122ed8260e001518360000151602001516020015187604001516020015160016138ef565b836060015160200151602001818152505061231b8260c00151836020015187602001516020015160006138ef565b6080840151515260e082015160208084015160408801519091015161234392919060006138ef565b608084015151602001525b509095945050505050565b8015610a44576000866001600160a01b0316633dbacd1a61237b878787613957565b846040518363ffffffff1660e01b8152600401612399929190615a2b565b6020604051808303816000875af11580156123b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dc9190615a39565b6040516261034760e41b815290915073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89063061034709061040f90899089908990899089908990600401615c3b565b8015610a44576000866001600160a01b0316633dbacd1a6124418787876139f8565b846040518363ffffffff1660e01b815260040161245f929190615a2b565b6020604051808303816000875af115801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a29190615a39565b604051636d6b205960e01b815290915073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c890636d6b20599061040f90899089908990899089908990600401615c3b565b6000836001600160a01b0316633e49bed061250085613a45565b846040518363ffffffff1660e01b815260040161251e929190615a2b565b6020604051808303816000875af115801561253d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190615a39565b60006040516020016114de9060208082526012908201527111955391125391d7d554111055115117d05560721b604082015260600190565b6000806125ae8460400151856060015161317f565b905080856001600160a01b031663bd02d0f56125ce876000015187613a88565b6040518263ffffffff1660e01b81526004016125ec91815260200190565b602060405180830381865afa158015612609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262d9190615a39565b61165f9190615c27565b60008161264557825161062a565b50506020015190565b60008061265c868685613ab9565b9050600061266c8787878761108c565b50509050600061268188886000015187612f4c565b90508061268e84846126a4565b6126989190615baf565b98975050505050505050565b600061062a838368327cb2734119d3b7a9601e1b612f3f565b6000806126ce610cf7888887613ab9565b905060006126dd888887613b17565b90508115806126ea575080155b156126fa5760009250505061165f565b6000612707878787613b5e565b90506000612718610cf78385615b85565b90506000876127305761272b8286615bea565b61273a565b61273a8583615bea565b9b9a5050505050505050505050565b60008084121561275a57508261278f565b600061276888848989613b97565b90506000612779610cf786846126a4565b9050808613612788578561278a565b805b925050505b9695505050505050565b60008061165f8484611736565b60006040516020016114de906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b6127f18282610631565b80606001516001600160a01b031681604001516001600160a01b03160361057d5780516040516332e6f44d60e21b81526106fa9190600401615b16565b60008061283c858585613bee565b90508060000361285057600091505061062a565b61165f8142615baf565b60008061286986868686613c09565b90508060000361287d57600091505061172e565b6000866001600160a01b0316637ae1cfca6040516020016128db9060208082526023908201527f534b49505f424f52524f57494e475f4645455f464f525f534d414c4c45525f5360408201526249444560e81b606082015260800190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161290f91815260200190565b602060405180830381865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129509190615af9565b905080156129b857600061296688886001613ab9565b9050600061297689896000613ab9565b905085801561298457508082105b1561299657600094505050505061172e565b851580156129a357508181105b156129b557600094505050505061172e565b50505b60006129c8888888886000613c45565b9050806000036129eb57604051630d5f5aef60e31b815260040160405180910390fd5b60006129fc89896000015188613cbe565b90508015612a1d57612a12898988878686613cd9565b94505050505061172e565b6000612a2e8a8a6000015189613e88565b90506000612a3c8683613ea3565b90506000612a4a8286613f02565b90506000612a5d8d8d600001518c613f10565b9050612a6982826126a4565b9d9c50505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a958585612ad0565b6040518263ffffffff1660e01b8152600401612ab391815260200190565b602060405180830381865afa15801561253d573d6000803e3d6000fd5b6000604051602001611254906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b6000612b4c6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b846001600160a01b031663bd02d0f5612b69866000015186613a88565b6040518263ffffffff1660e01b8152600401612b8791815260200190565b602060405180830381865afa158015612ba4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc89190615a39565b81528351612bd890869085613f2b565b602082015283516001600160a01b0386169063bd02d0f590612bfa9086613f46565b6040518263ffffffff1660e01b8152600401612c1891815260200190565b602060405180830381865afa158015612c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c599190615a39565b604082015283516001600160a01b0386169063bd02d0f590612c7b9086613f87565b6040518263ffffffff1660e01b8152600401612c9991815260200190565b602060405180830381865afa158015612cb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cda9190615a39565b606082015283516001600160a01b0386169063bd02d0f590612cfc9086613fc1565b6040518263ffffffff1660e01b8152600401612d1a91815260200190565b602060405180830381865afa158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5b9190615a39565b608082015283516001600160a01b0386169063bd02d0f590612d7d9086613ffe565b6040518263ffffffff1660e01b8152600401612d9b91815260200190565b602060405180830381865afa158015612db8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddc9190615a39565b60a0820181905260808201516060830151604084015160208501518551612e039190615b9c565b612e0d9190615b9c565b612e179190615b9c565b612e219190615b9c565b61165f9190615b9c565b600081866001600160a01b031663bd02d0f5612e48888888614034565b6040518263ffffffff1660e01b8152600401612e6691815260200190565b602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea79190615a39565b61278f9190615c27565b6000604051602001612eef9060208082526018908201527710d31052535050931157d1955391125391d7d05353d5539560421b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800161128a565b60008082121561161b578160000361032a565b600061172e848484614068565b6000836001600160a01b031663bd02d0f5612a9585855b6000604051602001611254906020808252600f908201526e544f54414c5f424f52524f57494e4760881b604082015260600190565b6000826001600160a01b031663bd02d0f5612fb28461313e565b6040518263ffffffff1660e01b8152600401612fd091815260200190565b602060405180830381865afa158015612fed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062a9190615a39565b60006040516020016114de9060208082526026908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554494f6040820152654e5f5241544560d01b606082015260800190565b60006040516020016114de906020808252601f908201527f4d494e5f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e5400604082015260600190565b600080836001600160a01b031663bd02d0f56130c185611f67565b6040518263ffffffff1660e01b81526004016130df91815260200190565b602060405180830381865afa1580156130fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131209190615a39565b90508060000361313457600091505061032a565b61172e8142615baf565b60006040516020016114de906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000816001600160a01b0316836001600160a01b0316146131a15760016131a4565b60025b60ff169392505050565b600081866001600160a01b031663bd02d0f5612e48888888614152565b600080836001600160a01b031663bd02d0f56130c185612561565b6000806000613241604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61324b8787614185565b81526132578688615b9c565b8160200181815250506132996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b896001600160a01b031663bd02d0f56132b18b6141a7565b6040518263ffffffff1660e01b81526004016132cf91815260200190565b602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190615a39565b6040820152815115801561332657506040810151155b1561333e5760006001600094509450945050506138e4565b8160200151600003613363576040516311423d9560e01b815260040160405180910390fd5b61336d8a8a6141f5565b60608301819052825161337f91613ea3565b6080830181905260208301516133959190613f02565b60a08301526040810151600003613465576133b08a8a61420f565b604083015260006001600160a01b038b1663bd02d0f56133cf8c614229565b6040518263ffffffff1660e01b81526004016133ed91815260200190565b602060405180830381865afa15801561340a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342e9190615a39565b905060006134448460a0015185604001516126a4565b9050818111156134515750805b955050508587119250600091506138e49050565b61346f8a8a61426c565b60c0830181905261347f90612f2c565b60e08301526001600160a01b038a1663bd02d0f561349c8b614286565b6040518263ffffffff1660e01b81526004016134ba91815260200190565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb9190615a39565b81526001600160a01b038a1663bd02d0f56135158b6142c8565b6040518263ffffffff1660e01b815260040161353391815260200190565b602060405180830381865afa158015613550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135749190615a39565b602082015260c082015161010083018190526000908190811280156135985750888a115b806135b1575060008460c001511280156135b157508989115b905080156135e957825160a085015111156135cf57600191506135ee565b82602001518460a0015110156135e457600291505b6135ee565b600191505b600182600281111561360257613602615c76565b0361365f576000613612896115b1565b613627610cf78760a0015187604001516126a4565b6136319190615c8c565b9050898b10156136475761364481615b40565b90505b808560c001516136579190615bc2565b610100860152505b600282600281111561367357613673615c76565b148015613683575060e084015115155b15613790578b6001600160a01b031663bd02d0f56136a08d61430b565b6040518263ffffffff1660e01b81526004016136be91815260200190565b602060405180830381865afa1580156136db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ff9190615a39565b60608401819052600090613714908a90615b85565b9050808560e00151116137485761372e8560e001516115b1565b8560c0015161373d9190615cbc565b61010086015261378e565b60006137578660e001516115b1565b8660c001516137669190615cbc565b90508061377c838860e00151610cf79190615baf565b6137869190615c8c565b610100870152505b505b8b6001600160a01b031663bd02d0f56137a88d614359565b6040518263ffffffff1660e01b81526004016137c691815260200190565b602060405180830381865afa1580156137e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138079190615a39565b60808401526001600160a01b038c1663bd02d0f56138248d614229565b6040518263ffffffff1660e01b815260040161384291815260200190565b602060405180830381865afa15801561385f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138839190615a39565b60a0840181905261010085015161389c9160009061439c565b6101008501819052608084015160a08501516138b992919061439c565b61012085018190526138ca90612f2c565b600085610120015113856101000151965096509650505050505b955095509592505050565b60008415806138fc575083155b156139095750600061172e565b60006139338661392c66038d7ea4c6800068327cb2734119d3b7a9601e1b615b85565b87866143fc565b9050821561394d576139458185614423565b91505061172e565b6139458482615c27565b6000604051602001613998906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016139989060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b60006040516020016114de906020808252601f908201527f53415645445f46554e44494e475f464143544f525f5045525f5345434f4e4400604082015260600190565b6000604051602001612eef906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b600080613ace8460400151856060015161317f565b90506000613ae7868660000151876040015187866131ae565b90506000613b00878760000151886060015188876131ae565b9050613b0c8183615b9c565b979650505050505050565b600080613b2c8460400151856060015161317f565b90506000613b4586866000015187604001518786614446565b90506000613b0087876000015188606001518887614446565b60008215613b7f5781613b72578351613b78565b83602001515b905061062a565b81613b8e57836020015161172e565b50509051919050565b6000846001600160a01b031663bd02d0f5613bb3868686614463565b6040518263ffffffff1660e01b8152600401613bd191815260200190565b602060405180830381865afa158015611707573d6000803e3d6000fd5b6000836001600160a01b031663bd02d0f5612a958585611202565b6000808215613c3a576000613c1f878786613b17565b855160200151909150613c329082615b85565b91505061172b565b61278f868685613ab9565b60008083613c57578560600151613c5d565b85604001515b90506000613c6c888884612599565b905060008415613c9a5785613c8957866040015160200151613c93565b8660200151602001515b9050613cb4565b85613caa57604087015151613cb1565b6020870151515b90505b6116a28183615b85565b6000836001600160a01b031663bd02d0f5612a9585856144d7565b600080613ce98888888888614511565b90506000886001600160a01b031663bd02d0f5613d0a8a600001518a61453f565b6040518263ffffffff1660e01b8152600401613d2891815260200190565b602060405180830381865afa158015613d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d699190615a39565b90506000613d7783836126a4565b90508483118015613d9357508468327cb2734119d3b7a9601e1b115b1561278a576000613da48685615baf565b905060008b6001600160a01b031663bd02d0f5613dc58d600001518d61457a565b6040518263ffffffff1660e01b8152600401613de391815260200190565b602060405180830381865afa158015613e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e249190615a39565b9050600084821115613e3d57613e3a8583615baf565b90505b6000613e558968327cb2734119d3b7a9601e1b615baf565b905080613e628584615b85565b613e6c9190615c27565b613e769086615b9c565b9e9d5050505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a9585856145ca565b600068327cb2734119d3b7a9601e1b831015613ec15750600061032a565b68327cb2734119d3b7a9601e1b8203613edb57508161032a565b6000613ef7613ee985614609565b613ef285614609565b61461a565b905061172e8161465c565b600061062a8383600061466d565b6000836001600160a01b031663bd02d0f5612a9585856146b5565b6000836001600160a01b031663bd02d0f5612a9585856146eb565b6000604051602001612eef906020808252601b908201527a10d31052535050931157d0d3d31310551154905317d05353d55395602a1b604082015260600190565b6000604051602001612eef9060208082526014908201527310d31052535050931157d1915157d05353d5539560621b604082015260600190565b6000604051602001612eef9060208082526017908201527610d31052535050931157d55257d1915157d05353d55395604a1b604082015260600190565b6000604051602001612eef9060208082526010908201526f10519192531250551157d49155d0549160821b604082015260600190565b6000604051602001613998906020808252600e908201526d434f4c4c41544552414c5f53554d60901b604082015260600190565b60008080600019858709858702925082811083820303915050806000036140a25783828161409857614098615c11565b049250505061062a565b8084116140e95760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016106fa565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001613998906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b600081831161419d576141988383615baf565b61062a565b61062a8284615baf565b60006040516020016114de9060208082526022908201527f46554e44494e475f494e4352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b6000826001600160a01b031663bd02d0f5612fb284614728565b6000826001600160a01b031663bd02d0f5612fb284614765565b60006040516020016114de906020808252601d908201527f4d41585f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000826001600160a01b031663dc97d962612fb284613a45565b60006040516020016114de906020808252601c908201527b5448524553484f4c445f464f525f535441424c455f46554e44494e4760201b604082015260600190565b60006040516020016114de906020808252601e908201527f5448524553484f4c445f464f525f44454352454153455f46554e44494e470000604082015260600190565b60006040516020016114de9060208082526022908201527f46554e44494e475f44454352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b60006040516020016114de906020808252601d908201527f4d494e5f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000806143a885612f2c565b9050838110156143b55750825b828111156143c05750815b600085156143e3576143d4610cf787612f2c565b6143de9087615cbc565b6143e6565b60015b9050806143f2836115b1565b61278f9190615c8c565b60008115614418576144118585856001614799565b905061172e565b61172b858585614068565b60008160016144328286615b9c565b61443c9190615baf565b61062a9190615c27565b600081866001600160a01b031663bd02d0f5612e488888886147ea565b6000604051602001614497906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a0016139d9565b60006040516020016112549060208082526014908201527327a82a24a6a0a62faaa9a0a3a2afa320a1aa27a960611b604082015260600190565b60008061452387876000015187614827565b9050600061453184836126a4565b905060006116a28683613f02565b6000604051602001611254906020808252601590820152742120a9a2afa127a92927aba4a723afa320a1aa27a960591b604082015260600190565b60006040516020016112549060208082526024908201527f41424f56455f4f5054494d414c5f55534147455f424f52524f57494e475f464160408201526321aa27a960e11b606082015260800190565b6000604051602001611254906020808252601990820152782127a92927aba4a723afa2ac2827a722a72a2fa320a1aa27a960391b604082015260600190565b600061032a64e8d4a5100083615c27565b60008260000361464257811561463157600061463b565b670de0b6b3a76400005b905061032a565b61062a61465761465185614842565b846148f8565b614904565b600061032a64e8d4a5100083615b85565b60008360000361467f5750600061062a565b811561469e57613b788468327cb2734119d3b7a9601e1b856001614799565b61172e8468327cb2734119d3b7a9601e1b85614068565b60006040516020016112549060208082526010908201526f2127a92927aba4a723afa320a1aa27a960811b604082015260600190565b6000604051602001612eef9060208082526017908201527614d5d05417d253541050d517d413d3d317d05353d55395604a1b604082015260600190565b60006040516020016114de90602080825260179082015276232aa72224a723afa2ac2827a722a72a2fa320a1aa27a960491b604082015260600190565b60006040516020016114de906020808252600e908201526d232aa72224a723afa320a1aa27a960911b604082015260600190565b6000806147a7868686614068565b905060018360028111156147bd576147bd615c76565b1480156147da5750600084806147d5576147d5615c11565b868809115b1561172b5761278f600182615b9c565b6000604051602001613998906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b6000836001600160a01b031663bd02d0f5612a95858561494a565b6000670de0b6b3a764000082101561487057604051633621413760e21b8152600481018390526024016106fa565b6000614885670de0b6b3a7640000840461498c565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff1981016148ae575050919050565b6706f05b59d3b200005b80156148f057670de0b6b3a7640000828002049150671bc16d674ec8000082106148e8579283019260019190911c905b60011c6148b8565b505050919050565b600061062a8383614a6f565b6000680a688906bd8b000000821061493257604051634a4f26f160e01b8152600481018390526024016106fa565b670de0b6b3a7640000604083901b0461062a81614b35565b6000604051602001611254906020808252601c908201527b27a822a72fa4a72a22a922a9aa2fa922a9a2a92b22afa320a1aa27a960211b604082015260600190565b6000600160801b82106149ac57608091821c916149a99082615b9c565b90505b600160401b82106149ca57604091821c916149c79082615b9c565b90505b600160201b82106149e857602091821c916149e59082615b9c565b90505b620100008210614a0557601091821c91614a029082615b9c565b90505b6101008210614a2157600891821c91614a1e9082615b9c565b90505b60108210614a3c57600491821c91614a399082615b9c565b90505b60048210614a5757600291821c91614a549082615b9c565b90505b60028210614a6a5761032a600182615b9c565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110614ab35760405163698d9a0160e11b8152600481018290526024016106fa565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff8211905082600003614af15780670de0b6b3a764000085040194505050505061032a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b821615614b555768016a09e667f3bcc9090260401c5b6001603e1b821615614b70576801306fe0a31b7152df0260401c5b6001603d1b821615614b8b576801172b83c7d517adce0260401c5b6001603c1b821615614ba65768010b5586cf9890f62a0260401c5b6001603b1b821615614bc1576801059b0d31585743ae0260401c5b6001603a1b821615614bdc57680102c9a3e778060ee70260401c5b600160391b821615614bf75768010163da9fb33356d80260401c5b600160381b821615614c1257680100b1afa5abcbed610260401c5b600160371b821615614c2d5768010058c86da1c09ea20260401c5b600160361b821615614c48576801002c605e2e8cec500260401c5b600160351b821615614c6357680100162f3904051fa10260401c5b600160341b821615614c7e576801000b175effdc76ba0260401c5b600160331b821615614c9957680100058ba01fb9f96d0260401c5b600160321b821615614cb45768010002c5cc37da94920260401c5b600160311b821615614ccf576801000162e525ee05470260401c5b600160301b821615614cea5768010000b17255775c040260401c5b6001602f1b821615614d05576801000058b91b5bc9ae0260401c5b6001602e1b821615614d2057680100002c5c89d5ec6d0260401c5b6001602d1b821615614d3b5768010000162e43f4f8310260401c5b6001602c1b821615614d5657680100000b1721bcfc9a0260401c5b6001602b1b821615614d715768010000058b90cf1e6e0260401c5b6001602a1b821615614d8c576801000002c5c863b73f0260401c5b600160291b821615614da757680100000162e430e5a20260401c5b600160281b821615614dc2576801000000b1721835510260401c5b600160271b821615614ddd57680100000058b90c0b490260401c5b600160261b821615614df85768010000002c5c8601cc0260401c5b600160251b821615614e13576801000000162e42fff00260401c5b600160241b821615614e2e5768010000000b17217fbb0260401c5b600160231b821615614e49576801000000058b90bfce0260401c5b600160221b821615614e6457680100000002c5c85fe30260401c5b600160211b821615614e7f5768010000000162e42ff10260401c5b600160201b821615614e9a57680100000000b17217f80260401c5b6380000000821615614eb55768010000000058b90bfc0260401c5b6340000000821615614ed0576801000000002c5c85fe0260401c5b6320000000821615614eeb57680100000000162e42ff0260401c5b6310000000821615614f06576801000000000b17217f0260401c5b6308000000821615614f2157680100000000058b90c00260401c5b6304000000821615614f3c5768010000000002c5c8600260401c5b6302000000821615614f57576801000000000162e4300260401c5b6301000000821615614f725768010000000000b172180260401c5b62800000821615614f8c576801000000000058b90c0260401c5b62400000821615614fa657680100000000002c5c860260401c5b62200000821615614fc05768010000000000162e430260401c5b62100000821615614fda57680100000000000b17210260401c5b62080000821615614ff45768010000000000058b910260401c5b6204000082161561500e576801000000000002c5c80260401c5b6202000082161561502857680100000000000162e40260401c5b620100008216156150415761b172600160401b010260401c5b618000821615615059576158b9600160401b010260401c5b61400082161561507157612c5d600160401b010260401c5b6120008216156150895761162e600160401b010260401c5b6110008216156150a157610b17600160401b010260401c5b6108008216156150b95761058c600160401b010260401c5b6104008216156150d1576102c6600160401b010260401c5b6102008216156150e957610163600160401b010260401c5b6101008216156151005760b1600160401b010260401c5b6080821615615116576059600160401b010260401c5b604082161561512c57602c600160401b010260401c5b6020821615615142576016600160401b010260401c5b601082161561515857600b600160401b010260401c5b600882161561516e576006600160401b010260401c5b6004821615615184576003600160401b010260401c5b600282161561519a576001600160401b010260401c5b60018216156151b0576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060001515815260200160008152602001600081526020016152796152d6565b81526020016152866152d6565b905290565b60405180610100016040528061529f6152d6565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60408051608081018252600091810182815260608201929092529081908152602001615286604051806040016040528060008152602001600081525090565b6001600160a01b038116811461532a57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156153655761536561532d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156153935761539361532d565b604052919050565b60006001600160401b038211156153b4576153b461532d565b5060051b60200190565b600080604083850312156153d157600080fd5b82356153dc81615315565b915060208301356001600160401b038111156153f757600080fd5b8301601f8101851361540857600080fd5b803561541b6154168261539b565b61536b565b8082825260208201915060208360051b85010192508783111561543d57600080fd5b6020840193505b8284101561546857833561545781615315565b825260209384019390910190615444565b809450505050509250929050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b602080825282518282018190526000918401906040840190835b8181101561234e576154d6838551615476565b60209390930192608092909201916001016154c3565b6000608082840312156154fe57600080fd5b615506615343565b9050813561551381615315565b8152602082013561552381615315565b6020820152604082013561553681615315565b6040820152606082013561554981615315565b606082015292915050565b60006040828403121561556657600080fd5b604080519081016001600160401b03811182821017156155885761558861532d565b604052823581526020928301359281019290925250919050565b600060c082840312156155b457600080fd5b604051606081016001600160401b03811182821017156155d6576155d661532d565b6040529050806155e68484615554565b81526155f58460408501615554565b60208201526156078460808501615554565b60408201525092915050565b801515811461532a57600080fd5b60008060008060006101a0868803121561563a57600080fd5b853561564581615315565b9450602086013561565581615315565b935061566487604088016154ec565b92506156738760c088016155a2565b915061018086013561568481615613565b809150509295509295909350565b6000602082840312156156a457600080fd5b813561062a81615315565b600080604083850312156156c257600080fd5b82356156cd81615315565b915060208301356156dd81615315565b809150509250929050565b60008060a083850312156156fb57600080fd5b823561570681615315565b915061571584602085016154ec565b90509250929050565b6080810161032a8284615476565b6000806040838503121561573f57600080fd5b823561574a81615315565b915060208301356001600160401b0381111561576557600080fd5b8301601f8101851361577657600080fd5b80356157846154168261539b565b8082825260208201915060208360071b8501019250878311156157a657600080fd5b6020840193505b82841015615468576157bf88856154ec565b82526020820191506080840193506157ad565b60008060008060008060006101a0888a0312156157ee57600080fd5b87356157f981615315565b96506158088960208a016154ec565b95506158178960a08a01615554565b94506158268960e08a01615554565b9350615836896101208a01615554565b9250610160880135915061018088013561584f81615613565b8091505092959891949750929550565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008101516101008301526101208101516101208301526101408101516101408301526101608101516101608301525050565b8281526101a0810161062a602083018461585f565b600080600080600080600060e0888a03121561590d57600080fd5b873561591881615315565b9650602088013561592881615315565b9550604088013561593881615613565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b60008060006060848603121561597557600080fd5b833561598081615315565b9250602084013561599081615315565b915060408401356159a081615315565b809150509250925092565b60008060008061018085870312156159c257600080fd5b84356159cd81615315565b935060208501356159dd81615315565b92506159ec86604087016154ec565b91506159fb8660c087016155a2565b905092959194509250565b610180810161032a828461585f565b634e487b7160e01b600052603260045260246000fd5b918252602082015260400190565b600060208284031215615a4b57600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0392831681529116602082015260400190565b60006080828403128015615aa357600080fd5b50615aac615343565b8251615ab781615315565b81526020830151615ac781615315565b60208201526040830151615ada81615315565b60408201526060830151615aed81615315565b60608201529392505050565b600060208284031215615b0b57600080fd5b815161062a81615613565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201615b5557615b55615b2a565b5060000390565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b808202811582820484141761032a5761032a615b2a565b8082018082111561032a5761032a615b2a565b8181038181111561032a5761032a615b2a565b8082018281126000831280158216821582161715615be257615be2615b2a565b505092915050565b8181036000831280158383131683831282161715615c0a57615c0a615b2a565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600082615c3657615c36615c11565b500490565b6001600160a01b039687168152948616602086015292909416604084015215156060830152608082019290925260a081019190915260c00190565b634e487b7160e01b600052602160045260246000fd5b80820260008212600160ff1b84141615615ca857615ca8615b2a565b818105831482151761032a5761032a615b2a565b600082615ccb57615ccb615c11565b600160ff1b821460001984141615615ce557615ce5615b2a565b50059056fea26469706673582212200886ae630b4cb6c475c2320c7e4eb1d8e6a12535ff34bb33942628fa8d94f4de64736f6c634300081d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100cf5760003560e01c80630988a8f7146100d45780631450a879146100fd57806316ba20891461011f5780631ded168e1461014057806339b1348f146101535780635930015e146101665780635d95a47e1461017957806361a6d817146101995780637b3435fc146101ac5780637b672c9a146101bf5780637d494dc3146101d2578063b656ff7a146101f3578063c468d13514610213578063d2ab7dc014610233578063f2e2a4f514610253575b600080fd5b6100e76100e23660046153be565b610273565b6040516100f491906154a9565b60405180910390f35b81801561010957600080fd5b5061011d610118366004615621565b610330565b005b61013261012d366004615692565b610448565b6040519081526020016100f4565b61011d61014e3660046156af565b6104ac565b61011d6101613660046156e8565b61053a565b61011d6101743660046156af565b610581565b61018c6101873660046156af565b610599565b6040516100f4919061571e565b61011d6101a73660046156e8565b610631565b61011d6101ba3660046153be565b610703565b61011d6101cd36600461572c565b61082d565b6101e56101e03660046157d2565b610864565b6040516100f49291906158dd565b8180156101ff57600080fd5b5061011d61020e3660046158f2565b6108fd565b81801561021f57600080fd5b5061011d61022e366004615960565b610927565b81801561023f57600080fd5b5061011d61024e3660046159ab565b610a4c565b6102666102613660046157d2565b610c6c565b6040516100f49190615a06565b6060600082516001600160401b038111156102905761029061532d565b6040519080825280602002602001820160405280156102c957816020015b6102b66151c7565b8152602001906001900390816102ae5790505b50905060005b83518110156103265760008482815181106102ec576102ec615a15565b602002602001015190506103008682610ffb565b83838151811061031257610312615a15565b6020908102919091010152506001016102cf565b5090505b92915050565b60008061033f8786868661108c565b92509250506103558787876000015186866110f2565b866001600160a01b031663e2a4853a610372876000015186611202565b426040518363ffffffff1660e01b8152600401610390929190615a2b565b6020604051808303816000875af11580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d39190615a39565b508451604051635375a20760e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__91635375a2079161040f918a918690600401615a52565b60006040518083038186803b15801561042757600080fd5b505af415801561043b573d6000803e3d6000fd5b5050505050505050505050565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032a9190615a39565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906104e89086908690600401615a76565b608060405180830381865af4158015610505573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105299190615a90565b90506105358382610631565b505050565b610549828283604001516112a8565b80606001516001600160a01b031681604001516001600160a01b03160361056e575050565b61057d828283606001516112a8565b5050565b600061058d8383610599565b9050610535838261053a565b6105a16151c7565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906105dd9087908790600401615a76565b608060405180830381865af41580156105fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061e9190615a90565b905061062a8482610631565b9392505050565b80516001600160a01b0316610659576040516302fde0d760e11b815260040160405180910390fd5b6000826001600160a01b0316637ae1cfca61067784600001516114a6565b6040518263ffffffff1660e01b815260040161069591815260200190565b602060405180830381865afa1580156106b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d69190615af9565b905080156105355781516040516309f8c93760e01b81526106fa9190600401615b16565b60405180910390fd5b6000826001600160a01b031663bd02d0f560405160200161074c9060208082526014908201527309a82b0bea6ae82a0bea082a890be988a9c8ea8960631b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161078091815260200190565b602060405180830381865afa15801561079d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c19190615a39565b905080825111156107ea57815181604051639da3604360e01b81526004016106fa929190615a2b565b60005b825181101561082757600083828151811061080a5761080a615a15565b6020026020010151905061081e8582611528565b506001016107ed565b50505050565b60005b81518110156105355761085c8383838151811061084f5761084f615a15565b602002602001015161053a565b600101610830565b600061086e6151ee565b600061087d8960000151610448565b905060006108908b8b8b8b8b8b8b610c6c565b9050816000036108ba576108af68327cb2734119d3b7a9601e1b6115b1565b935091506108f19050565b80516000036108d0576000935091506108f19050565b60006108e9670de0b6b3a764000083600001518561161f565b945090925050505b97509795505050505050565b600061090e88888888888888611668565b905061091c888888846116af565b505050505050505050565b6000806109348584611736565b91509150816000146109cb5761095d85858561094f866115b1565b61095890615b40565b6118cc565b604051633a5d319360e21b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063e974c64c9061099a908790879087908790600401615b5c565b60006040518083038186803b1580156109b257600080fd5b505af41580156109c6573d6000803e3d6000fd5b505050505b846001600160a01b031663e2a4853a6109e385611f67565b426040518363ffffffff1660e01b8152600401610a01929190615a2b565b6020604051808303816000875af1158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190615a39565b505050505050565b6000610a59858484611fb6565b9050610a7e858585600001518660400151600186606001516000015160000151612359565b610aa1858585600001518660400151600086606001516020015160000151612359565b610ac4858585600001518660600151600186606001516000015160200151612359565b610ae7858585600001518660600151600086606001516020015160200151612359565b8251604084015160808301515151610b05928892889260019061241f565b610b2885858560000151866040015160008660800151602001516000015161241f565b610b4b85858560000151866060015160018660800151600001516020015161241f565b610b6e85858560000151866060015160008660800151602001516020015161241f565b610b8185846000015183604001516124e6565b50846001600160a01b031663e2a4853a610b9e8560000151612561565b426040518363ffffffff1660e01b8152600401610bbc929190615a2b565b6020604051808303816000875af1158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190615a39565b508251602082015160405163387a0f1360e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9263387a0f1392610c409289929190600401615a52565b60006040518083038186803b158015610c5857600080fd5b505af415801561091c573d6000803e3d6000fd5b610c746151ee565b610c7c6151ee565b610c8b89898a60400151612599565b60808201526060880151610ca2908a908a90612599565b60a0820152610cb18684612637565b8160800151610cc09190615b85565b60c0820152610ccf8584612637565b8160a00151610cde9190615b85565b60e0820181905260c0820151610cfc91610cf791615b9c565b6115b1565b81526040805160608101825288815260208101889052908101869052610d258a8a83600161264e565b610100830152610d388a8a83600061264e565b8261010001818151610d4a9190615b9c565b9052506040516001600160a01b038b169063bd02d0f590610d9f906020016020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610dd391815260200190565b602060405180830381865afa158015610df0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e149190615a39565b610e2a9068327cb2734119d3b7a9601e1b615baf565b6101208301819052610100830151610e4691610cf791906126a4565b82518390610e55908390615bc2565b905250610e678a8a8a600188156126bd565b60208301819052895160c0840151610e86928d9291600191908a612749565b6020830152610e9a8a8a8a600088156126bd565b60408301819052895160e0840151610eb9928d9291600091908a612749565b604083018190526020830151610ecf9190615bc2565b606083018190528251610ee29190615bea565b82528851610ef1908b90612799565b6101408301526000610f04898615612637565b836101400151610f149190615b85565b9050610f1f816115b1565b83518490610f2e908390615bea565b90525089516001600160a01b038c169063bd02d0f590610f4d906127a6565b6040518263ffffffff1660e01b8152600401610f6b91815260200190565b602060405180830381865afa158015610f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fac9190615a39565b6101608401526000610fbe8a87612637565b846101600151610fce9190615b85565b9050610fd9816115b1565b84518590610fe8908390615bc2565b905250929b9a5050505050505050505050565b6110036151c7565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff59061103f9087908790600401615a76565b608060405180830381865af415801561105c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110809190615a90565b905061062a84826127e7565b6000806000806110a18888600001518761282e565b905060006110b18989898961285a565b905060006110c48a8a6000015189612a7a565b905060006110d28385615b85565b905060006110e08284615b9c565b9c919b50929950975050505050505050565b6000856001600160a01b031663340dbab361110d8686612ad0565b846040518363ffffffff1660e01b815260040161112b929190615a2b565b6020604051808303816000875af115801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e9190615a39565b60405163d206b70560e01b81526001600160a01b038088166004830152861660248201528415156044820152606481018490526084810182905290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063d206b7059060a40160006040518083038186803b1580156111e257600080fd5b505af41580156111f6573d6000803e3d6000fd5b50505050505050505050565b60006040516020016112549060208082526026908201527f43554d554c41544956455f424f52524f57494e475f464143544f525f5550444160408201526515115117d05560d21b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0385169082015282151560608201526080015b60405160208183030381529060405280519060200120905092915050565b81516001600160a01b031615806112c657506001600160a01b038116155b156112e957815160405163e474a42560e01b81526106fa91908390600401615a76565b81516040516370a0823160e01b81526000916001600160a01b038416916370a082319161131891600401615b16565b602060405180830381865afa158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190615a39565b90506000611368858585612b11565b9050808210156113945783516040516333a1ea6b60e01b81526106fa9190859085908590600401615b5c565b60006113a886866000015186600180612e2b565b90506113bd8686600001518660006001612e2b565b6113c79082615b9c565b9050808310156113f357845160405163808c464f60e01b81526106fa9190869086908590600401615b5c565b6000866001600160a01b031663bd02d0f5611412886000015188612eb1565b6040518263ffffffff1660e01b815260040161143091815260200190565b602060405180830381865afa15801561144d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114719190615a39565b90508084101561149d578551604051639dd026db60e01b81526106fa9190879087908590600401615b5c565b50505050505050565b60006040516020016114de906020808252601290820152711254d7d3505492d15517d11254d05093115160721b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906115649086908690600401615a76565b608060405180830381865af4158015611581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a59190615a90565b905061053583826127e7565b60006001600160ff1b0382111561161b5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016106fa565b5090565b6000806116358561162f86612f2c565b85612f3f565b90506000841361165657611648816115b1565b61165190615b40565b61165f565b61165f816115b1565b95945050505050565b600080611676898989612f4c565b905061168286866126a4565b61168c9082615baf565b905061169884846126a4565b6116a29082615b9c565b9998505050505050505050565b6000846001600160a01b031663e2a4853a6116ca8686612f63565b846040518363ffffffff1660e01b81526004016116e8929190615a2b565b6020604051808303816000875af1158015611707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172b9190615a39565b90505b949350505050565b60008060006117458585612f98565b90508060000361175a576000925090506118c5565b6000856001600160a01b031663bd02d0f561177487613011565b6040518263ffffffff1660e01b815260040161179291815260200190565b602060405180830381865afa1580156117af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d39190615a39565b9050806000036117e957506000925090506118c5565b6000866001600160a01b031663bd02d0f561180388613063565b6040518263ffffffff1660e01b815260040161182191815260200190565b602060405180830381865afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190615a39565b905080831161187a57600083945094505050506118c5565b60006118868285615baf565b9050600061189489896130a6565b905060006118a282866126a4565b9050828111156118af5750815b806118ba8188615baf565b975097505050505050505b9250929050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915261190782612f2c565b60408201526000821215611c625761191e8361313e565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b9190615a39565b6060820181905260408201511115611bac57806060015181604001516119b19190615baf565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a916119e69190600090600401615a2b565b6020604051808303816000875af1158015611a05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a299190615a39565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585611a5385606001516115b1565b60006040518563ffffffff1660e01b8152600401611a749493929190615b5c565b60006040518083038186803b158015611a8c57600080fd5b505af4158015611aa0573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611abc856127a6565b83608001516040518363ffffffff1660e01b8152600401611ade929190615a2b565b6020604051808303816000875af1158015611afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b219190615a39565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818585611b5385608001516115b1565b8560a001516040518563ffffffff1660e01b8152600401611b779493929190615b5c565b60006040518083038186803b158015611b8f57600080fd5b505af4158015611ba3573d6000803e3d6000fd5b50505050611f60565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611bdd92600401615a2b565b6020604051808303816000875af1158015611bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c209190615a39565b60a0820181905260405163555a997960e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9163555a997991611b7791889188918891600401615b5c565b611c6b836127a6565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611cb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdc9190615a39565b6060820181905260408201511115611ea75780606001518160400151611d029190615baf565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a91611d3a9190600090600401615a2b565b6020604051808303816000875af1158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d9190615a39565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818585611da785606001516115b1565b60006040518563ffffffff1660e01b8152600401611dc89493929190615b5c565b60006040518083038186803b158015611de057600080fd5b505af4158015611df4573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3611e108561313e565b83608001516040518363ffffffff1660e01b8152600401611e32929190615a2b565b6020604051808303816000875af1158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190615a39565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585611b5385608001516115b1565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc192611edb92600401615a2b565b6020604051808303816000875af1158015611efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1e9190615a39565b60a08201819052604051634ddb3d8160e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__91634ddb3d8191610c4091889188918891600401615b5c565b5050505050565b60006040516020016114de9060208082526023908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554454460408201526217d05560ea1b606082015260800190565b611fbe61524f565b611fc661524f565b611fce61528b565b6000611fe28660400151876060015161317f565b9050611ffa87876000015188604001516001856131ae565b82515152855160608701516120139189916001856131ae565b825151602001528551604087015161202f9189916000856131ae565b825160200151528551606087015161204b9189916000856131ae565b825160209081015181019190915282515190810151905161206c9190615b9c565b602080840191909152825181015190810151905161208a9190615b9c565b6040830152602082015115806120a257506040820151155b156120b25782935050505061062a565b6120c08787600001516131cb565b606083018190528651602084015160408501516120e1938b939291906131e6565b604086015215158085526020850191909152612101578160400151612107565b81602001515b608083018190526020840151606084015161212b929161212691615b85565b6126a4565b60a0830181905261213d908290615c27565b60a083015282511561218e5760a0820151825151516020840151612162929190612f3f565b60c083015260a082015182515160209081015190840151612184929190612f3f565b60e08301526121d4565b60a08201518251602001515160408401516121aa929190612f3f565b60c083015260a08201518251602090810151015160408401516121ce929190612f3f565b60e08301525b8251156122925760c08201518251515160208088015101516121f992919060016138ef565b6060840151515260e082015182515160209081015160408801519091015161222492919060016138ef565b83606001516000015160200181815250506122528260c00151836040015187602001516020015160006138ef565b83608001516020015160000181815250506122808260e00151836040015187604001516020015160006138ef565b6080840151602090810151015261234e565b6122b78260c001518360000151602001516000015187602001516020015160016138ef565b83606001516020015160000181815250506122ed8260e001518360000151602001516020015187604001516020015160016138ef565b836060015160200151602001818152505061231b8260c00151836020015187602001516020015160006138ef565b6080840151515260e082015160208084015160408801519091015161234392919060006138ef565b608084015151602001525b509095945050505050565b8015610a44576000866001600160a01b0316633dbacd1a61237b878787613957565b846040518363ffffffff1660e01b8152600401612399929190615a2b565b6020604051808303816000875af11580156123b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dc9190615a39565b6040516261034760e41b815290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063061034709061040f90899089908990899089908990600401615c3b565b8015610a44576000866001600160a01b0316633dbacd1a6124418787876139f8565b846040518363ffffffff1660e01b815260040161245f929190615a2b565b6020604051808303816000875af115801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a29190615a39565b604051636d6b205960e01b815290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__90636d6b20599061040f90899089908990899089908990600401615c3b565b6000836001600160a01b0316633e49bed061250085613a45565b846040518363ffffffff1660e01b815260040161251e929190615a2b565b6020604051808303816000875af115801561253d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190615a39565b60006040516020016114de9060208082526012908201527111955391125391d7d554111055115117d05560721b604082015260600190565b6000806125ae8460400151856060015161317f565b905080856001600160a01b031663bd02d0f56125ce876000015187613a88565b6040518263ffffffff1660e01b81526004016125ec91815260200190565b602060405180830381865afa158015612609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262d9190615a39565b61165f9190615c27565b60008161264557825161062a565b50506020015190565b60008061265c868685613ab9565b9050600061266c8787878761108c565b50509050600061268188886000015187612f4c565b90508061268e84846126a4565b6126989190615baf565b98975050505050505050565b600061062a838368327cb2734119d3b7a9601e1b612f3f565b6000806126ce610cf7888887613ab9565b905060006126dd888887613b17565b90508115806126ea575080155b156126fa5760009250505061165f565b6000612707878787613b5e565b90506000612718610cf78385615b85565b90506000876127305761272b8286615bea565b61273a565b61273a8583615bea565b9b9a5050505050505050505050565b60008084121561275a57508261278f565b600061276888848989613b97565b90506000612779610cf786846126a4565b9050808613612788578561278a565b805b925050505b9695505050505050565b60008061165f8484611736565b60006040516020016114de906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b6127f18282610631565b80606001516001600160a01b031681604001516001600160a01b03160361057d5780516040516332e6f44d60e21b81526106fa9190600401615b16565b60008061283c858585613bee565b90508060000361285057600091505061062a565b61165f8142615baf565b60008061286986868686613c09565b90508060000361287d57600091505061172e565b6000866001600160a01b0316637ae1cfca6040516020016128db9060208082526023908201527f534b49505f424f52524f57494e475f4645455f464f525f534d414c4c45525f5360408201526249444560e81b606082015260800190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161290f91815260200190565b602060405180830381865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129509190615af9565b905080156129b857600061296688886001613ab9565b9050600061297689896000613ab9565b905085801561298457508082105b1561299657600094505050505061172e565b851580156129a357508181105b156129b557600094505050505061172e565b50505b60006129c8888888886000613c45565b9050806000036129eb57604051630d5f5aef60e31b815260040160405180910390fd5b60006129fc89896000015188613cbe565b90508015612a1d57612a12898988878686613cd9565b94505050505061172e565b6000612a2e8a8a6000015189613e88565b90506000612a3c8683613ea3565b90506000612a4a8286613f02565b90506000612a5d8d8d600001518c613f10565b9050612a6982826126a4565b9d9c50505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a958585612ad0565b6040518263ffffffff1660e01b8152600401612ab391815260200190565b602060405180830381865afa15801561253d573d6000803e3d6000fd5b6000604051602001611254906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b6000612b4c6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b846001600160a01b031663bd02d0f5612b69866000015186613a88565b6040518263ffffffff1660e01b8152600401612b8791815260200190565b602060405180830381865afa158015612ba4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc89190615a39565b81528351612bd890869085613f2b565b602082015283516001600160a01b0386169063bd02d0f590612bfa9086613f46565b6040518263ffffffff1660e01b8152600401612c1891815260200190565b602060405180830381865afa158015612c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c599190615a39565b604082015283516001600160a01b0386169063bd02d0f590612c7b9086613f87565b6040518263ffffffff1660e01b8152600401612c9991815260200190565b602060405180830381865afa158015612cb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cda9190615a39565b606082015283516001600160a01b0386169063bd02d0f590612cfc9086613fc1565b6040518263ffffffff1660e01b8152600401612d1a91815260200190565b602060405180830381865afa158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5b9190615a39565b608082015283516001600160a01b0386169063bd02d0f590612d7d9086613ffe565b6040518263ffffffff1660e01b8152600401612d9b91815260200190565b602060405180830381865afa158015612db8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddc9190615a39565b60a0820181905260808201516060830151604084015160208501518551612e039190615b9c565b612e0d9190615b9c565b612e179190615b9c565b612e219190615b9c565b61165f9190615b9c565b600081866001600160a01b031663bd02d0f5612e48888888614034565b6040518263ffffffff1660e01b8152600401612e6691815260200190565b602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea79190615a39565b61278f9190615c27565b6000604051602001612eef9060208082526018908201527710d31052535050931157d1955391125391d7d05353d5539560421b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800161128a565b60008082121561161b578160000361032a565b600061172e848484614068565b6000836001600160a01b031663bd02d0f5612a9585855b6000604051602001611254906020808252600f908201526e544f54414c5f424f52524f57494e4760881b604082015260600190565b6000826001600160a01b031663bd02d0f5612fb28461313e565b6040518263ffffffff1660e01b8152600401612fd091815260200190565b602060405180830381865afa158015612fed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062a9190615a39565b60006040516020016114de9060208082526026908201527f504f534954494f4e5f494d504143545f504f4f4c5f444953545249425554494f6040820152654e5f5241544560d01b606082015260800190565b60006040516020016114de906020808252601f908201527f4d494e5f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e5400604082015260600190565b600080836001600160a01b031663bd02d0f56130c185611f67565b6040518263ffffffff1660e01b81526004016130df91815260200190565b602060405180830381865afa1580156130fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131209190615a39565b90508060000361313457600091505061032a565b61172e8142615baf565b60006040516020016114de906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000816001600160a01b0316836001600160a01b0316146131a15760016131a4565b60025b60ff169392505050565b600081866001600160a01b031663bd02d0f5612e48888888614152565b600080836001600160a01b031663bd02d0f56130c185612561565b6000806000613241604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61324b8787614185565b81526132578688615b9c565b8160200181815250506132996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b896001600160a01b031663bd02d0f56132b18b6141a7565b6040518263ffffffff1660e01b81526004016132cf91815260200190565b602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190615a39565b6040820152815115801561332657506040810151155b1561333e5760006001600094509450945050506138e4565b8160200151600003613363576040516311423d9560e01b815260040160405180910390fd5b61336d8a8a6141f5565b60608301819052825161337f91613ea3565b6080830181905260208301516133959190613f02565b60a08301526040810151600003613465576133b08a8a61420f565b604083015260006001600160a01b038b1663bd02d0f56133cf8c614229565b6040518263ffffffff1660e01b81526004016133ed91815260200190565b602060405180830381865afa15801561340a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342e9190615a39565b905060006134448460a0015185604001516126a4565b9050818111156134515750805b955050508587119250600091506138e49050565b61346f8a8a61426c565b60c0830181905261347f90612f2c565b60e08301526001600160a01b038a1663bd02d0f561349c8b614286565b6040518263ffffffff1660e01b81526004016134ba91815260200190565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb9190615a39565b81526001600160a01b038a1663bd02d0f56135158b6142c8565b6040518263ffffffff1660e01b815260040161353391815260200190565b602060405180830381865afa158015613550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135749190615a39565b602082015260c082015161010083018190526000908190811280156135985750888a115b806135b1575060008460c001511280156135b157508989115b905080156135e957825160a085015111156135cf57600191506135ee565b82602001518460a0015110156135e457600291505b6135ee565b600191505b600182600281111561360257613602615c76565b0361365f576000613612896115b1565b613627610cf78760a0015187604001516126a4565b6136319190615c8c565b9050898b10156136475761364481615b40565b90505b808560c001516136579190615bc2565b610100860152505b600282600281111561367357613673615c76565b148015613683575060e084015115155b15613790578b6001600160a01b031663bd02d0f56136a08d61430b565b6040518263ffffffff1660e01b81526004016136be91815260200190565b602060405180830381865afa1580156136db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ff9190615a39565b60608401819052600090613714908a90615b85565b9050808560e00151116137485761372e8560e001516115b1565b8560c0015161373d9190615cbc565b61010086015261378e565b60006137578660e001516115b1565b8660c001516137669190615cbc565b90508061377c838860e00151610cf79190615baf565b6137869190615c8c565b610100870152505b505b8b6001600160a01b031663bd02d0f56137a88d614359565b6040518263ffffffff1660e01b81526004016137c691815260200190565b602060405180830381865afa1580156137e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138079190615a39565b60808401526001600160a01b038c1663bd02d0f56138248d614229565b6040518263ffffffff1660e01b815260040161384291815260200190565b602060405180830381865afa15801561385f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138839190615a39565b60a0840181905261010085015161389c9160009061439c565b6101008501819052608084015160a08501516138b992919061439c565b61012085018190526138ca90612f2c565b600085610120015113856101000151965096509650505050505b955095509592505050565b60008415806138fc575083155b156139095750600061172e565b60006139338661392c66038d7ea4c6800068327cb2734119d3b7a9601e1b615b85565b87866143fc565b9050821561394d576139458185614423565b91505061172e565b6139458482615c27565b6000604051602001613998906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016139989060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b60006040516020016114de906020808252601f908201527f53415645445f46554e44494e475f464143544f525f5045525f5345434f4e4400604082015260600190565b6000604051602001612eef906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b600080613ace8460400151856060015161317f565b90506000613ae7868660000151876040015187866131ae565b90506000613b00878760000151886060015188876131ae565b9050613b0c8183615b9c565b979650505050505050565b600080613b2c8460400151856060015161317f565b90506000613b4586866000015187604001518786614446565b90506000613b0087876000015188606001518887614446565b60008215613b7f5781613b72578351613b78565b83602001515b905061062a565b81613b8e57836020015161172e565b50509051919050565b6000846001600160a01b031663bd02d0f5613bb3868686614463565b6040518263ffffffff1660e01b8152600401613bd191815260200190565b602060405180830381865afa158015611707573d6000803e3d6000fd5b6000836001600160a01b031663bd02d0f5612a958585611202565b6000808215613c3a576000613c1f878786613b17565b855160200151909150613c329082615b85565b91505061172b565b61278f868685613ab9565b60008083613c57578560600151613c5d565b85604001515b90506000613c6c888884612599565b905060008415613c9a5785613c8957866040015160200151613c93565b8660200151602001515b9050613cb4565b85613caa57604087015151613cb1565b6020870151515b90505b6116a28183615b85565b6000836001600160a01b031663bd02d0f5612a9585856144d7565b600080613ce98888888888614511565b90506000886001600160a01b031663bd02d0f5613d0a8a600001518a61453f565b6040518263ffffffff1660e01b8152600401613d2891815260200190565b602060405180830381865afa158015613d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d699190615a39565b90506000613d7783836126a4565b90508483118015613d9357508468327cb2734119d3b7a9601e1b115b1561278a576000613da48685615baf565b905060008b6001600160a01b031663bd02d0f5613dc58d600001518d61457a565b6040518263ffffffff1660e01b8152600401613de391815260200190565b602060405180830381865afa158015613e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e249190615a39565b9050600084821115613e3d57613e3a8583615baf565b90505b6000613e558968327cb2734119d3b7a9601e1b615baf565b905080613e628584615b85565b613e6c9190615c27565b613e769086615b9c565b9e9d5050505050505050505050505050565b6000836001600160a01b031663bd02d0f5612a9585856145ca565b600068327cb2734119d3b7a9601e1b831015613ec15750600061032a565b68327cb2734119d3b7a9601e1b8203613edb57508161032a565b6000613ef7613ee985614609565b613ef285614609565b61461a565b905061172e8161465c565b600061062a8383600061466d565b6000836001600160a01b031663bd02d0f5612a9585856146b5565b6000836001600160a01b031663bd02d0f5612a9585856146eb565b6000604051602001612eef906020808252601b908201527a10d31052535050931157d0d3d31310551154905317d05353d55395602a1b604082015260600190565b6000604051602001612eef9060208082526014908201527310d31052535050931157d1915157d05353d5539560621b604082015260600190565b6000604051602001612eef9060208082526017908201527610d31052535050931157d55257d1915157d05353d55395604a1b604082015260600190565b6000604051602001612eef9060208082526010908201526f10519192531250551157d49155d0549160821b604082015260600190565b6000604051602001613998906020808252600e908201526d434f4c4c41544552414c5f53554d60901b604082015260600190565b60008080600019858709858702925082811083820303915050806000036140a25783828161409857614098615c11565b049250505061062a565b8084116140e95760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016106fa565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001613998906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b600081831161419d576141988383615baf565b61062a565b61062a8284615baf565b60006040516020016114de9060208082526022908201527f46554e44494e475f494e4352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b6000826001600160a01b031663bd02d0f5612fb284614728565b6000826001600160a01b031663bd02d0f5612fb284614765565b60006040516020016114de906020808252601d908201527f4d41585f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000826001600160a01b031663dc97d962612fb284613a45565b60006040516020016114de906020808252601c908201527b5448524553484f4c445f464f525f535441424c455f46554e44494e4760201b604082015260600190565b60006040516020016114de906020808252601e908201527f5448524553484f4c445f464f525f44454352454153455f46554e44494e470000604082015260600190565b60006040516020016114de9060208082526022908201527f46554e44494e475f44454352454153455f464143544f525f5045525f5345434f604082015261139160f21b606082015260800190565b60006040516020016114de906020808252601d908201527f4d494e5f46554e44494e475f464143544f525f5045525f5345434f4e44000000604082015260600190565b6000806143a885612f2c565b9050838110156143b55750825b828111156143c05750815b600085156143e3576143d4610cf787612f2c565b6143de9087615cbc565b6143e6565b60015b9050806143f2836115b1565b61278f9190615c8c565b60008115614418576144118585856001614799565b905061172e565b61172b858585614068565b60008160016144328286615b9c565b61443c9190615baf565b61062a9190615c27565b600081866001600160a01b031663bd02d0f5612e488888886147ea565b6000604051602001614497906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a0016139d9565b60006040516020016112549060208082526014908201527327a82a24a6a0a62faaa9a0a3a2afa320a1aa27a960611b604082015260600190565b60008061452387876000015187614827565b9050600061453184836126a4565b905060006116a28683613f02565b6000604051602001611254906020808252601590820152742120a9a2afa127a92927aba4a723afa320a1aa27a960591b604082015260600190565b60006040516020016112549060208082526024908201527f41424f56455f4f5054494d414c5f55534147455f424f52524f57494e475f464160408201526321aa27a960e11b606082015260800190565b6000604051602001611254906020808252601990820152782127a92927aba4a723afa2ac2827a722a72a2fa320a1aa27a960391b604082015260600190565b600061032a64e8d4a5100083615c27565b60008260000361464257811561463157600061463b565b670de0b6b3a76400005b905061032a565b61062a61465761465185614842565b846148f8565b614904565b600061032a64e8d4a5100083615b85565b60008360000361467f5750600061062a565b811561469e57613b788468327cb2734119d3b7a9601e1b856001614799565b61172e8468327cb2734119d3b7a9601e1b85614068565b60006040516020016112549060208082526010908201526f2127a92927aba4a723afa320a1aa27a960811b604082015260600190565b6000604051602001612eef9060208082526017908201527614d5d05417d253541050d517d413d3d317d05353d55395604a1b604082015260600190565b60006040516020016114de90602080825260179082015276232aa72224a723afa2ac2827a722a72a2fa320a1aa27a960491b604082015260600190565b60006040516020016114de906020808252600e908201526d232aa72224a723afa320a1aa27a960911b604082015260600190565b6000806147a7868686614068565b905060018360028111156147bd576147bd615c76565b1480156147da5750600084806147d5576147d5615c11565b868809115b1561172b5761278f600182615b9c565b6000604051602001613998906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b6000836001600160a01b031663bd02d0f5612a95858561494a565b6000670de0b6b3a764000082101561487057604051633621413760e21b8152600481018390526024016106fa565b6000614885670de0b6b3a7640000840461498c565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff1981016148ae575050919050565b6706f05b59d3b200005b80156148f057670de0b6b3a7640000828002049150671bc16d674ec8000082106148e8579283019260019190911c905b60011c6148b8565b505050919050565b600061062a8383614a6f565b6000680a688906bd8b000000821061493257604051634a4f26f160e01b8152600481018390526024016106fa565b670de0b6b3a7640000604083901b0461062a81614b35565b6000604051602001611254906020808252601c908201527b27a822a72fa4a72a22a922a9aa2fa922a9a2a92b22afa320a1aa27a960211b604082015260600190565b6000600160801b82106149ac57608091821c916149a99082615b9c565b90505b600160401b82106149ca57604091821c916149c79082615b9c565b90505b600160201b82106149e857602091821c916149e59082615b9c565b90505b620100008210614a0557601091821c91614a029082615b9c565b90505b6101008210614a2157600891821c91614a1e9082615b9c565b90505b60108210614a3c57600491821c91614a399082615b9c565b90505b60048210614a5757600291821c91614a549082615b9c565b90505b60028210614a6a5761032a600182615b9c565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110614ab35760405163698d9a0160e11b8152600481018290526024016106fa565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff8211905082600003614af15780670de0b6b3a764000085040194505050505061032a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b821615614b555768016a09e667f3bcc9090260401c5b6001603e1b821615614b70576801306fe0a31b7152df0260401c5b6001603d1b821615614b8b576801172b83c7d517adce0260401c5b6001603c1b821615614ba65768010b5586cf9890f62a0260401c5b6001603b1b821615614bc1576801059b0d31585743ae0260401c5b6001603a1b821615614bdc57680102c9a3e778060ee70260401c5b600160391b821615614bf75768010163da9fb33356d80260401c5b600160381b821615614c1257680100b1afa5abcbed610260401c5b600160371b821615614c2d5768010058c86da1c09ea20260401c5b600160361b821615614c48576801002c605e2e8cec500260401c5b600160351b821615614c6357680100162f3904051fa10260401c5b600160341b821615614c7e576801000b175effdc76ba0260401c5b600160331b821615614c9957680100058ba01fb9f96d0260401c5b600160321b821615614cb45768010002c5cc37da94920260401c5b600160311b821615614ccf576801000162e525ee05470260401c5b600160301b821615614cea5768010000b17255775c040260401c5b6001602f1b821615614d05576801000058b91b5bc9ae0260401c5b6001602e1b821615614d2057680100002c5c89d5ec6d0260401c5b6001602d1b821615614d3b5768010000162e43f4f8310260401c5b6001602c1b821615614d5657680100000b1721bcfc9a0260401c5b6001602b1b821615614d715768010000058b90cf1e6e0260401c5b6001602a1b821615614d8c576801000002c5c863b73f0260401c5b600160291b821615614da757680100000162e430e5a20260401c5b600160281b821615614dc2576801000000b1721835510260401c5b600160271b821615614ddd57680100000058b90c0b490260401c5b600160261b821615614df85768010000002c5c8601cc0260401c5b600160251b821615614e13576801000000162e42fff00260401c5b600160241b821615614e2e5768010000000b17217fbb0260401c5b600160231b821615614e49576801000000058b90bfce0260401c5b600160221b821615614e6457680100000002c5c85fe30260401c5b600160211b821615614e7f5768010000000162e42ff10260401c5b600160201b821615614e9a57680100000000b17217f80260401c5b6380000000821615614eb55768010000000058b90bfc0260401c5b6340000000821615614ed0576801000000002c5c85fe0260401c5b6320000000821615614eeb57680100000000162e42ff0260401c5b6310000000821615614f06576801000000000b17217f0260401c5b6308000000821615614f2157680100000000058b90c00260401c5b6304000000821615614f3c5768010000000002c5c8600260401c5b6302000000821615614f57576801000000000162e4300260401c5b6301000000821615614f725768010000000000b172180260401c5b62800000821615614f8c576801000000000058b90c0260401c5b62400000821615614fa657680100000000002c5c860260401c5b62200000821615614fc05768010000000000162e430260401c5b62100000821615614fda57680100000000000b17210260401c5b62080000821615614ff45768010000000000058b910260401c5b6204000082161561500e576801000000000002c5c80260401c5b6202000082161561502857680100000000000162e40260401c5b620100008216156150415761b172600160401b010260401c5b618000821615615059576158b9600160401b010260401c5b61400082161561507157612c5d600160401b010260401c5b6120008216156150895761162e600160401b010260401c5b6110008216156150a157610b17600160401b010260401c5b6108008216156150b95761058c600160401b010260401c5b6104008216156150d1576102c6600160401b010260401c5b6102008216156150e957610163600160401b010260401c5b6101008216156151005760b1600160401b010260401c5b6080821615615116576059600160401b010260401c5b604082161561512c57602c600160401b010260401c5b6020821615615142576016600160401b010260401c5b601082161561515857600b600160401b010260401c5b600882161561516e576006600160401b010260401c5b6004821615615184576003600160401b010260401c5b600282161561519a576001600160401b010260401c5b60018216156151b0576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060001515815260200160008152602001600081526020016152796152d6565b81526020016152866152d6565b905290565b60405180610100016040528061529f6152d6565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60408051608081018252600091810182815260608201929092529081908152602001615286604051806040016040528060008152602001600081525090565b6001600160a01b038116811461532a57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156153655761536561532d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156153935761539361532d565b604052919050565b60006001600160401b038211156153b4576153b461532d565b5060051b60200190565b600080604083850312156153d157600080fd5b82356153dc81615315565b915060208301356001600160401b038111156153f757600080fd5b8301601f8101851361540857600080fd5b803561541b6154168261539b565b61536b565b8082825260208201915060208360051b85010192508783111561543d57600080fd5b6020840193505b8284101561546857833561545781615315565b825260209384019390910190615444565b809450505050509250929050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b602080825282518282018190526000918401906040840190835b8181101561234e576154d6838551615476565b60209390930192608092909201916001016154c3565b6000608082840312156154fe57600080fd5b615506615343565b9050813561551381615315565b8152602082013561552381615315565b6020820152604082013561553681615315565b6040820152606082013561554981615315565b606082015292915050565b60006040828403121561556657600080fd5b604080519081016001600160401b03811182821017156155885761558861532d565b604052823581526020928301359281019290925250919050565b600060c082840312156155b457600080fd5b604051606081016001600160401b03811182821017156155d6576155d661532d565b6040529050806155e68484615554565b81526155f58460408501615554565b60208201526156078460808501615554565b60408201525092915050565b801515811461532a57600080fd5b60008060008060006101a0868803121561563a57600080fd5b853561564581615315565b9450602086013561565581615315565b935061566487604088016154ec565b92506156738760c088016155a2565b915061018086013561568481615613565b809150509295509295909350565b6000602082840312156156a457600080fd5b813561062a81615315565b600080604083850312156156c257600080fd5b82356156cd81615315565b915060208301356156dd81615315565b809150509250929050565b60008060a083850312156156fb57600080fd5b823561570681615315565b915061571584602085016154ec565b90509250929050565b6080810161032a8284615476565b6000806040838503121561573f57600080fd5b823561574a81615315565b915060208301356001600160401b0381111561576557600080fd5b8301601f8101851361577657600080fd5b80356157846154168261539b565b8082825260208201915060208360071b8501019250878311156157a657600080fd5b6020840193505b82841015615468576157bf88856154ec565b82526020820191506080840193506157ad565b60008060008060008060006101a0888a0312156157ee57600080fd5b87356157f981615315565b96506158088960208a016154ec565b95506158178960a08a01615554565b94506158268960e08a01615554565b9350615836896101208a01615554565b9250610160880135915061018088013561584f81615613565b8091505092959891949750929550565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008101516101008301526101208101516101208301526101408101516101408301526101608101516101608301525050565b8281526101a0810161062a602083018461585f565b600080600080600080600060e0888a03121561590d57600080fd5b873561591881615315565b9650602088013561592881615315565b9550604088013561593881615613565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b60008060006060848603121561597557600080fd5b833561598081615315565b9250602084013561599081615315565b915060408401356159a081615315565b809150509250925092565b60008060008061018085870312156159c257600080fd5b84356159cd81615315565b935060208501356159dd81615315565b92506159ec86604087016154ec565b91506159fb8660c087016155a2565b905092959194509250565b610180810161032a828461585f565b634e487b7160e01b600052603260045260246000fd5b918252602082015260400190565b600060208284031215615a4b57600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0392831681529116602082015260400190565b60006080828403128015615aa357600080fd5b50615aac615343565b8251615ab781615315565b81526020830151615ac781615315565b60208201526040830151615ada81615315565b60408201526060830151615aed81615315565b60608201529392505050565b600060208284031215615b0b57600080fd5b815161062a81615613565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201615b5557615b55615b2a565b5060000390565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b808202811582820484141761032a5761032a615b2a565b8082018082111561032a5761032a615b2a565b8181038181111561032a5761032a615b2a565b8082018281126000831280158216821582161715615be257615be2615b2a565b505092915050565b8181036000831280158383131683831282161715615c0a57615c0a615b2a565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600082615c3657615c36615c11565b500490565b6001600160a01b039687168152948616602086015292909416604084015215156060830152608082019290925260a081019190915260c00190565b634e487b7160e01b600052602160045260246000fd5b80820260008212600160ff1b84141615615ca857615ca8615b2a565b818105831482151761032a5761032a615b2a565b600082615ccb57615ccb615c11565b600160ff1b821460001984141615615ce557615ce5615b2a565b50059056fea26469706673582212200886ae630b4cb6c475c2320c7e4eb1d8e6a12535ff34bb33942628fa8d94f4de64736f6c634300081d0033", "libraries": { - "MarketEventUtils": "0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8", - "MarketStoreUtils": "0xd727120ac811e9136D4a5D5C6219aEE37e275785" + "MarketEventUtils": "0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8", + "MarketStoreUtils": "0x2e5D10A48C00cFcc6A31af873118d739323Ff71B" }, "devdoc": { "kind": "dev", diff --git a/deployments/arbitrum/PositionImpactPoolUtils.json b/deployments/arbitrum/PositionImpactPoolUtils.json index 11c03ac21..e8951ebaf 100644 --- a/deployments/arbitrum/PositionImpactPoolUtils.json +++ b/deployments/arbitrum/PositionImpactPoolUtils.json @@ -1,5 +1,5 @@ { - "address": "0x87a0d100b4F9b2A53353974c3596eEC33de8060f", + "address": "0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3", "abi": [ { "inputs": [ @@ -66,33 +66,33 @@ "type": "error" } ], - "transactionHash": "0x90ea36bb406b90d50b733c97a33a45c2d246ad18bb386f32d4424a99a0444690", + "transactionHash": "0x7d767015d8a163314c0589666e19a56d392f40bc74e29bbc2683cd803a55cfc2", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0x87a0d100b4F9b2A53353974c3596eEC33de8060f", + "contractAddress": "0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3", "transactionIndex": 5, - "gasUsed": "2129178", + "gasUsed": "2121578", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9634131ed10d9beced8302d045eb9cf7b8148613fb29b504d1d19384bd222db0", - "transactionHash": "0x90ea36bb406b90d50b733c97a33a45c2d246ad18bb386f32d4424a99a0444690", + "blockHash": "0x7333019e4446b2a91e693d428dc1632cff680fb34ac3ffbd867fee5054b507b5", + "transactionHash": "0x7d767015d8a163314c0589666e19a56d392f40bc74e29bbc2683cd803a55cfc2", "logs": [], - "blockNumber": 367563518, - "cumulativeGasUsed": "2328794", + "blockNumber": 390053945, + "cumulativeGasUsed": "3768538", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "79ca35a0eb57a5a4e0af2a0fc5a1dbeb", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolValue\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"totalPendingImpactAmount\",\"type\":\"int256\"}],\"name\":\"InsufficientImpactPoolValueForWithdrawal\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"poolValue\",\"type\":\"int256\"}],\"name\":\"InvalidPoolValueForWithdrawal\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lentAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReductionAmount\",\"type\":\"uint256\"}],\"name\":\"ReductionExceedsLentAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"UnexpectedTokenForVirtualInventory\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/PositionImpactPoolUtils.sol\":\"PositionImpactPoolUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/market/PositionImpactPoolUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {Market} from \\\"./Market.sol\\\";\\nimport {MarketEventUtils} from \\\"./MarketEventUtils.sol\\\";\\nimport {MarketPoolValueInfo} from \\\"./MarketPoolValueInfo.sol\\\";\\nimport {MarketStoreUtils} from \\\"./MarketStoreUtils.sol\\\";\\nimport {MarketToken} from \\\"./MarketToken.sol\\\";\\nimport {MarketUtils} from \\\"./MarketUtils.sol\\\";\\nimport {SafeCast} from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IOracle } from \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../position/PositionUtils.sol\\\";\\n\\nlibrary PositionImpactPoolUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n using SafeERC20 for IERC20;\\n\\n using Market for Market.Props;\\n\\n // @dev withdraw funds from the position impact pool while maintaining GM token price\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param receiver the address to receive the withdrawn funds\\n // @param amount the amount to withdraw\\n // @param oracle - oracle to fetch the market prices\\n function withdrawFromPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n require(amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n MarketUtils.distributePositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market\\n );\\n\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\\n dataStore,\\n marketProps,\\n prices.indexTokenPrice,\\n prices.longTokenPrice,\\n prices.shortTokenPrice,\\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\\n false\\n );\\n\\n if (poolValueInfo.poolValue <= 0) {\\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\\n }\\n\\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\\n\\n // if there is a positive totalPendingImpactAmount, that means that the\\n // excess should be covered by the position impact pool, so subtract this\\n // from the impactPoolAmount that can be withdrawn\\n // lent amount is not considered here, because if there is a lent amount\\n // we assume that the position impact would be zero\\n if (totalPendingImpactAmount > 0) {\\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\\n }\\n\\n if (adjustedImpactPoolAmount < amount) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n MarketUtils.applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n - amount.toInt256()\\n );\\n\\n // Calculate amount of tokens to withdraw:\\n // We want to withdraw long and short tokens from the pool\\n // at the current pool token ratio\\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\\n dataStore,\\n marketProps,\\n prices,\\n amount * prices.indexTokenPrice.min\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n - longTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n - shortTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.longToken,\\n receiver,\\n longTokenWithdrawalAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.shortToken,\\n receiver,\\n shortTokenWithdrawalAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\\n eventEmitter,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external {\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\\n\\n if (reductionAmount > lentAmount) {\\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\\n }\\n\\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\\n\\n if (longTokenAmount > 0) {\\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\\n }\\n\\n if (shortTokenAmount > 0) {\\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\\n }\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n longTokenAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n shortTokenAmount.toInt256()\\n );\\n\\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitLentImpactAmountReduction(\\n eventEmitter,\\n market,\\n fundingAccount,\\n longTokenAmount,\\n shortTokenAmount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe74b2dfdd27d92eb33535d5c5fe4af456d05c180d17d8252f5728c62dd1293b0\",\"license\":\"BUSL-1.1\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n // @dev IsPositionLiquidatableCache struct used in isPositionLiquidatable\\n // to avoid stack too deep errors\\n // @param positionPnlUsd the position's pnl in USD\\n // @param minCollateralFactor the min collateral factor\\n // @param collateralTokenPrice the collateral token price\\n // @param collateralUsd the position's collateral in USD\\n // @param usdDeltaForPriceImpact the usdDelta value for the price impact calculation\\n // @param priceImpactUsd the price impact of closing the position in USD\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n // @dev check if a position is liquidatable\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0x98416c7f41b0baf01552655c8034e98c71f204b6449fa967c44eb2df84391fab\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x6124ea610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631483c5fc146100455780639166d48114610067575b600080fd5b81801561005157600080fd5b50610065610060366004611f89565b610087565b005b81801561007357600080fd5b50610065610082366004611f89565b610666565b600081116100dc5760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e203000000060448201526064015b60405180910390fd5b60405163c468d13560e01b81526001600160a01b03808816600483015280871660248301528416604482015273F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d969063c468d1359060640160006040518083038186803b15801561013f57600080fd5b505af4158015610153573d6000803e3d6000fd5b505060405163a8d8fff560e01b81526000925073d727120ac811e9136D4a5D5C6219aEE37e275785915063a8d8fff590610193908a908890600401612002565b608060405180830381865af41580156101b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d49190612053565b905060006101e28683610a8f565b604051631ce5b4e360e21b815290915073f718aE0025504577b18f8773e56986B6e29C819F90637396d38c90610222908b908b9087908790600401612129565b60006040518083038186803b15801561023a57600080fd5b505af415801561024e573d6000803e3d6000fd5b50505050600073F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d9663f2e2a4f58a858560000151866020015187604001516040516020016102c0906020808252601e908201527f4d41585f504e4c5f464143544f525f464f525f5749544844524157414c530000604082015260600190565b6040516020818303038152906040528051906020012060006040518863ffffffff1660e01b81526004016102fa979695949392919061218e565b61018060405180830381865af4158015610318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033c91906121f0565b905060008160000151136103695780516040516390a6af3b60e01b815260048101919091526024016100d3565b610140810151600061037b8b89610c07565b905060008113156103dd5761038f81610c87565b8210156103c757610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6103d081610c87565b6103da90836122a6565b91505b8582101561041657610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6104338b8b8a6104258a610cdd565b61042e906122b9565b610d47565b6000806104558d88888960000151600001518c61045091906122d5565b611413565b9150915061047b8d8d898a6040015161046d87610cdd565b610476906122b9565b6114d3565b506104908d8d898a6060015161046d86610cdd565b50604080880151905163078d3b7960e01b81526001600160a01b038c169163078d3b79916104c591908d9087906004016122ec565b600060405180830381600087803b1580156104df57600080fd5b505af11580156104f3573d6000803e3d6000fd5b505050606088015160405163078d3b7960e01b81526001600160a01b038d16925063078d3b799161052a918d9086906004016122ec565b600060405180830381600087803b15801561054457600080fd5b505af1158015610558573d6000803e3d6000fd5b5050505073F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96635930015e8e8c6040518363ffffffff1660e01b8152600401610595929190612002565b60006040518083038186803b1580156105ad57600080fd5b505af41580156105c1573d6000803e3d6000fd5b5050604051635bb3aa7360e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc89250635bb3aa739150610627908f908e908e908e906004016001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b60006040518083038186803b15801561063f57600080fd5b505af4158015610653573d6000803e3d6000fd5b5050505050505050505050505050505050565b60405163a8d8fff560e01b815260009073d727120ac811e9136D4a5D5C6219aEE37e2757859063a8d8fff5906106a2908a908890600401612002565b608060405180830381865af41580156106bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e39190612053565b905060006106f18683610a8f565b604051631ce5b4e360e21b815290915073f718aE0025504577b18f8773e56986B6e29C819F90637396d38c90610731908b908b9087908790600401612129565b60006040518083038186803b15801561074957600080fd5b505af415801561075d573d6000803e3d6000fd5b505050506000886001600160a01b031663bd02d0f561077b88611643565b6040518263ffffffff1660e01b815260040161079991815260200190565b602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190612310565b90508084111561080157808460405163eef4e17160e01b81526004016100d3929190612329565b81516020015160009061081490866122d5565b9050600061083682856020015160000151600261083191906122d5565b6116ce565b9050600061085383866040015160000151600261083191906122d5565b90508115610875576040860151610875906001600160a01b0316898b856116f1565b8015610895576060860151610895906001600160a01b0316898b846116f1565b6108a98c8c88896040015161047687610cdd565b506108be8c8c88896060015161047686610cdd565b5060008c6001600160a01b031663e98aabc16108d98c611643565b8a6040518363ffffffff1660e01b81526004016108f7929190612329565b6020604051808303816000875af1158015610916573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093a9190612310565b905073C1bd1ad41cda5C5c5953766CbA5c375c85407cc8634ddb3d818d8c6109618c610cdd565b856040518563ffffffff1660e01b81526004016109819493929190612337565b60006040518083038186803b15801561099957600080fd5b505af41580156109ad573d6000803e3d6000fd5b5050505073F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96635930015e8e8c6040518363ffffffff1660e01b81526004016109ea929190612002565b60006040518083038186803b158015610a0257600080fd5b505af4158015610a16573d6000803e3d6000fd5b5050505073C1bd1ad41cda5C5c5953766CbA5c375c85407cc863850310d78d8c8c87878e6040518763ffffffff1660e01b8152600401610627969594939291906001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b610a97611f25565b6040518060600160405280846001600160a01b0316635dcf719485602001516040518263ffffffff1660e01b8152600401610ad29190612360565b6040805180830381865afa158015610aee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b129190612374565b8152602001846001600160a01b0316635dcf719485604001516040518263ffffffff1660e01b8152600401610b479190612360565b6040805180830381865afa158015610b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b879190612374565b8152602001846001600160a01b0316635dcf719485606001516040518263ffffffff1660e01b8152600401610bbc9190612360565b6040805180830381865afa158015610bd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfc9190612374565b905290505b92915050565b6000826001600160a01b031663dc97d962610c218461174f565b6040518263ffffffff1660e01b8152600401610c3f91815260200190565b602060405180830381865afa158015610c5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c809190612310565b9392505050565b600080821215610cd95760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016100d3565b5090565b60006001600160ff1b03821115610cd95760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016100d3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152610d8282611790565b604082015260008212156110dd57610d99836117a1565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015610de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e069190612310565b60608201819052604082015111156110275780606001518160400151610e2c91906122a6565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a91610e619190600090600401612329565b6020604051808303816000875af1158015610e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea49190612310565b5073C1bd1ad41cda5C5c5953766CbA5c375c85407cc863555a99798585610ece8560600151610cdd565b60006040518563ffffffff1660e01b8152600401610eef9493929190612337565b60006040518083038186803b158015610f0757600080fd5b505af4158015610f1b573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3610f3785611643565b83608001516040518363ffffffff1660e01b8152600401610f59929190612329565b6020604051808303816000875af1158015610f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9c9190612310565b8160a001818152505073C1bd1ad41cda5C5c5953766CbA5c375c85407cc8634ddb3d818585610fce8560800151610cdd565b8560a001516040518563ffffffff1660e01b8152600401610ff29493929190612337565b60006040518083038186803b15801561100a57600080fd5b505af415801561101e573d6000803e3d6000fd5b5050505061140c565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261105892600401612329565b6020604051808303816000875af1158015611077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109b9190612310565b60a0820181905260405163555a997960e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc89163555a997991610ff291889188918891600401612337565b6110e683611643565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190612310565b6060820181905260408201511115611322578060600151816040015161117d91906122a6565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a916111b59190600090600401612329565b6020604051808303816000875af11580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f89190612310565b5073C1bd1ad41cda5C5c5953766CbA5c375c85407cc8634ddb3d8185856112228560600151610cdd565b60006040518563ffffffff1660e01b81526004016112439493929190612337565b60006040518083038186803b15801561125b57600080fd5b505af415801561126f573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab361128b856117a1565b83608001516040518363ffffffff1660e01b81526004016112ad929190612329565b6020604051808303816000875af11580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190612310565b8160a001818152505073C1bd1ad41cda5C5c5953766CbA5c375c85407cc863555a99798585610fce8560800151610cdd565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261135692600401612329565b6020604051808303816000875af1158015611375573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113999190612310565b60a08201819052604051634ddb3d8160e01b815273C1bd1ad41cda5C5c5953766CbA5c375c85407cc891634ddb3d81916113db91889188918891600401612337565b60006040518083038186803b1580156113f357600080fd5b505af4158015611407573d6000803e3d6000fd5b505050505b5050505050565b6000806000611427878788604001516117e2565b9050600061143a888889606001516117e2565b905060008660200151602001518361145291906122d5565b905060008760400151602001518361146a91906122d5565b9050600061147882846123d4565b90506000611487898584611889565b905060006114968a8585611889565b90508a6020015160200151826114ac91906123fd565b60408c0151602001516114bf90836123fd565b985098505050505050505094509492505050565b600080866001600160a01b03166332f85bbf6114f387600001518761189e565b6040516001600160e01b031960e084901b16815260048101919091526024810186905260606044820152602260648201527f496e76616c69642073746174652c206e6567617469766520706f6f6c416d6f756084820152611b9d60f21b60a482015260c4016020604051808303816000875af1158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b9190612310565b90506115aa8787878787611926565b50508451604051631daaefa160e01b81526001600160a01b03808916600483015291821660248201529085166044820152606481018490526084810182905273C1bd1ad41cda5C5c5953766CbA5c375c85407cc890631daaefa19060a40160006040518083038186803b15801561162057600080fd5b505af4158015611634573d6000803e3d6000fd5b50929998505050505050505050565b6000604051602001611684906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60008160016116dd82866123d4565b6116e791906122a6565b610c8091906123fd565b611749846323b872dd60e01b858585604051602401611712939291906122ec565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611aee565b50505050565b6000604051602001611684906020808252601b908201527a1513d5105317d4115391125391d7d253541050d517d05353d55395602a1b604082015260600190565b600080821215610cd9575060000390565b6000604051602001611684906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000806117f784604001518560600151611bc8565b905080856001600160a01b031663bd02d0f561181787600001518761189e565b6040518263ffffffff1660e01b815260040161183591815260200190565b602060405180830381865afa158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190612310565b61188091906123fd565b95945050505050565b6000611896848484611bf7565b949350505050565b60006040516020016118cf906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b6000806000876001600160a01b031663a6ed563e6119478860000151611ce1565b6040518263ffffffff1660e01b815260040161196591815260200190565b602060405180830381865afa158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a69190612310565b9050806119ba576000809250925050611ae4565b60006119c68787611d18565b90506000896001600160a01b0316638ca498b06119e38585611d90565b886040518363ffffffff1660e01b8152600401611a01929190612329565b6020604051808303816000875af1158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a449190612310565b885160405163a814bb6f60e01b81526001600160a01b03808d16600483015290911660248201528315156044820152606481018590526084810188905260a4810182905290915073C1bd1ad41cda5C5c5953766CbA5c375c85407cc89063a814bb6f9060c40160006040518083038186803b158015611ac257600080fd5b505af4158015611ad6573d6000803e3d6000fd5b506001975092955050505050505b9550959350505050565b6000611b43826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e029092919063ffffffff16565b9050805160001480611b64575080806020019051810190611b64919061241f565b611bc35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100d3565b505050565b6000816001600160a01b0316836001600160a01b031614611bea576001611bed565b60025b60ff169392505050565b6000808060001985870985870292508281108382030391505080600003611c3157838281611c2757611c276123e7565b0492505050610c80565b808411611c785760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016100d3565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001611684906020808252601190820152701592549515505317d3505492d15517d251607a1b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614158015611d56575082606001516001600160a01b0316826001600160a01b031614155b15611d7857825160405163785ee46960e01b81526100d3918491600401612002565b506040909101516001600160a01b0391821691161490565b6000604051602001611dd1906020808252601b908201527a5649525455414c5f494e56454e544f52595f464f525f535741505360281b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018490528215156060820152608001611908565b6060611896848460008585600080866001600160a01b03168587604051611e299190612465565b60006040518083038185875af1925050503d8060008114611e66576040519150601f19603f3d011682016040523d82523d6000602084013e611e6b565b606091505b5091509150611e7c87838387611e87565b979650505050505050565b60608315611ef6578251600003611eef576001600160a01b0385163b611eef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100d3565b5081611896565b6118968383815115611f0b5781518083602001fd5b8060405162461bcd60e51b81526004016100d39190612481565b6040518060600160405280611f38611f57565b8152602001611f45611f57565b8152602001611f52611f57565b905290565b604051806040016040528060008152602001600081525090565b6001600160a01b0381168114611f8657600080fd5b50565b60008060008060008060c08789031215611fa257600080fd5b8635611fad81611f71565b95506020870135611fbd81611f71565b94506040870135611fcd81611f71565b93506060870135611fdd81611f71565b92506080870135611fed81611f71565b8092505060a087013590509295509295509295565b6001600160a01b0392831681529116602082015260400190565b60405161018081016001600160401b038111828210171561204d57634e487b7160e01b600052604160045260246000fd5b60405290565b6000608082840312801561206657600080fd5b50604051608081016001600160401b038111828210171561209757634e487b7160e01b600052604160045260246000fd5b60405282516120a581611f71565b815260208301516120b581611f71565b602082015260408301516120c881611f71565b604082015260608301516120db81611f71565b60608201529392505050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b80518252602090810151910152565b6001600160a01b03858116825284166020820152610180810161214f60408301856120e7565b61215d60c08301845161211a565b602083015161217061010084018261211a565b50604083015161218461014084018261211a565b5095945050505050565b6001600160a01b03881681526101a081016121ac60208301896120e7565b6121b960a083018861211a565b6121c660e083018761211a565b6121d461012083018661211a565b8361016083015282151561018083015298975050505050505050565b600061018082840312801561220457600080fd5b50600061220f61201c565b835181526020808501519082015260408085015190820152606080850151908201526080808501519082015260a0808501519082015260c0808501519082015260e080850151908201526101008085015190820152610120808501519082015261014080850151908201526101609384015193810193909352509092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c0157610c01612290565b6000600160ff1b82016122ce576122ce612290565b5060000390565b8082028115828204841417610c0157610c01612290565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561232257600080fd5b5051919050565b918252602082015260400190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b0391909116815260200190565b6000604082840312801561238757600080fd5b506040805160009181016001600160401b03811182821017156123b857634e487b7160e01b83526041600452602483fd5b6040528351815260209384015193810193909352509092915050565b80820180821115610c0157610c01612290565b634e487b7160e01b600052601260045260246000fd5b60008261241a57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561243157600080fd5b81518015158114610c8057600080fd5b60005b8381101561245c578181015183820152602001612444565b50506000910152565b60008251612477818460208701612441565b9190910192915050565b60208152600082518060208401526124a0816040850160208701612441565b601f01601f1916919091016040019291505056fea26469706673582212201fffeaf6073b022864b42425218c2f1035cd51775570cec3491c6edc9bee7bb064736f6c634300081d0033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631483c5fc146100455780639166d48114610067575b600080fd5b81801561005157600080fd5b50610065610060366004611f89565b610087565b005b81801561007357600080fd5b50610065610082366004611f89565b610666565b600081116100dc5760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e203000000060448201526064015b60405180910390fd5b60405163c468d13560e01b81526001600160a01b03808816600483015280871660248301528416604482015273__$e53db83827f4e07ebc418caf7145b8c2d5$__9063c468d1359060640160006040518083038186803b15801561013f57600080fd5b505af4158015610153573d6000803e3d6000fd5b505060405163a8d8fff560e01b81526000925073__$ff439aa65a80c9eec648f15db20b189505$__915063a8d8fff590610193908a908890600401612002565b608060405180830381865af41580156101b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d49190612053565b905060006101e28683610a8f565b604051631ce5b4e360e21b815290915073__$91a1a7f12f728c8759f4be979bae55555f$__90637396d38c90610222908b908b9087908790600401612129565b60006040518083038186803b15801561023a57600080fd5b505af415801561024e573d6000803e3d6000fd5b50505050600073__$e53db83827f4e07ebc418caf7145b8c2d5$__63f2e2a4f58a858560000151866020015187604001516040516020016102c0906020808252601e908201527f4d41585f504e4c5f464143544f525f464f525f5749544844524157414c530000604082015260600190565b6040516020818303038152906040528051906020012060006040518863ffffffff1660e01b81526004016102fa979695949392919061218e565b61018060405180830381865af4158015610318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033c91906121f0565b905060008160000151136103695780516040516390a6af3b60e01b815260048101919091526024016100d3565b610140810151600061037b8b89610c07565b905060008113156103dd5761038f81610c87565b8210156103c757610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6103d081610c87565b6103da90836122a6565b91505b8582101561041657610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6104338b8b8a6104258a610cdd565b61042e906122b9565b610d47565b6000806104558d88888960000151600001518c61045091906122d5565b611413565b9150915061047b8d8d898a6040015161046d87610cdd565b610476906122b9565b6114d3565b506104908d8d898a6060015161046d86610cdd565b50604080880151905163078d3b7960e01b81526001600160a01b038c169163078d3b79916104c591908d9087906004016122ec565b600060405180830381600087803b1580156104df57600080fd5b505af11580156104f3573d6000803e3d6000fd5b505050606088015160405163078d3b7960e01b81526001600160a01b038d16925063078d3b799161052a918d9086906004016122ec565b600060405180830381600087803b15801561054457600080fd5b505af1158015610558573d6000803e3d6000fd5b5050505073__$e53db83827f4e07ebc418caf7145b8c2d5$__635930015e8e8c6040518363ffffffff1660e01b8152600401610595929190612002565b60006040518083038186803b1580156105ad57600080fd5b505af41580156105c1573d6000803e3d6000fd5b5050604051635bb3aa7360e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9250635bb3aa739150610627908f908e908e908e906004016001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b60006040518083038186803b15801561063f57600080fd5b505af4158015610653573d6000803e3d6000fd5b5050505050505050505050505050505050565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906106a2908a908890600401612002565b608060405180830381865af41580156106bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e39190612053565b905060006106f18683610a8f565b604051631ce5b4e360e21b815290915073__$91a1a7f12f728c8759f4be979bae55555f$__90637396d38c90610731908b908b9087908790600401612129565b60006040518083038186803b15801561074957600080fd5b505af415801561075d573d6000803e3d6000fd5b505050506000886001600160a01b031663bd02d0f561077b88611643565b6040518263ffffffff1660e01b815260040161079991815260200190565b602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190612310565b90508084111561080157808460405163eef4e17160e01b81526004016100d3929190612329565b81516020015160009061081490866122d5565b9050600061083682856020015160000151600261083191906122d5565b6116ce565b9050600061085383866040015160000151600261083191906122d5565b90508115610875576040860151610875906001600160a01b0316898b856116f1565b8015610895576060860151610895906001600160a01b0316898b846116f1565b6108a98c8c88896040015161047687610cdd565b506108be8c8c88896060015161047686610cdd565b5060008c6001600160a01b031663e98aabc16108d98c611643565b8a6040518363ffffffff1660e01b81526004016108f7929190612329565b6020604051808303816000875af1158015610916573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093a9190612310565b905073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818d8c6109618c610cdd565b856040518563ffffffff1660e01b81526004016109819493929190612337565b60006040518083038186803b15801561099957600080fd5b505af41580156109ad573d6000803e3d6000fd5b5050505073__$e53db83827f4e07ebc418caf7145b8c2d5$__635930015e8e8c6040518363ffffffff1660e01b81526004016109ea929190612002565b60006040518083038186803b158015610a0257600080fd5b505af4158015610a16573d6000803e3d6000fd5b5050505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63850310d78d8c8c87878e6040518763ffffffff1660e01b8152600401610627969594939291906001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b610a97611f25565b6040518060600160405280846001600160a01b0316635dcf719485602001516040518263ffffffff1660e01b8152600401610ad29190612360565b6040805180830381865afa158015610aee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b129190612374565b8152602001846001600160a01b0316635dcf719485604001516040518263ffffffff1660e01b8152600401610b479190612360565b6040805180830381865afa158015610b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b879190612374565b8152602001846001600160a01b0316635dcf719485606001516040518263ffffffff1660e01b8152600401610bbc9190612360565b6040805180830381865afa158015610bd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfc9190612374565b905290505b92915050565b6000826001600160a01b031663dc97d962610c218461174f565b6040518263ffffffff1660e01b8152600401610c3f91815260200190565b602060405180830381865afa158015610c5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c809190612310565b9392505050565b600080821215610cd95760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016100d3565b5090565b60006001600160ff1b03821115610cd95760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016100d3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152610d8282611790565b604082015260008212156110dd57610d99836117a1565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015610de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e069190612310565b60608201819052604082015111156110275780606001518160400151610e2c91906122a6565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a91610e619190600090600401612329565b6020604051808303816000875af1158015610e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea49190612310565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585610ece8560600151610cdd565b60006040518563ffffffff1660e01b8152600401610eef9493929190612337565b60006040518083038186803b158015610f0757600080fd5b505af4158015610f1b573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3610f3785611643565b83608001516040518363ffffffff1660e01b8152600401610f59929190612329565b6020604051808303816000875af1158015610f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9c9190612310565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818585610fce8560800151610cdd565b8560a001516040518563ffffffff1660e01b8152600401610ff29493929190612337565b60006040518083038186803b15801561100a57600080fd5b505af415801561101e573d6000803e3d6000fd5b5050505061140c565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261105892600401612329565b6020604051808303816000875af1158015611077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109b9190612310565b60a0820181905260405163555a997960e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9163555a997991610ff291889188918891600401612337565b6110e683611643565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190612310565b6060820181905260408201511115611322578060600151816040015161117d91906122a6565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a916111b59190600090600401612329565b6020604051808303816000875af11580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f89190612310565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d8185856112228560600151610cdd565b60006040518563ffffffff1660e01b81526004016112439493929190612337565b60006040518083038186803b15801561125b57600080fd5b505af415801561126f573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab361128b856117a1565b83608001516040518363ffffffff1660e01b81526004016112ad929190612329565b6020604051808303816000875af11580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190612310565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585610fce8560800151610cdd565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261135692600401612329565b6020604051808303816000875af1158015611375573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113999190612310565b60a08201819052604051634ddb3d8160e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__91634ddb3d81916113db91889188918891600401612337565b60006040518083038186803b1580156113f357600080fd5b505af4158015611407573d6000803e3d6000fd5b505050505b5050505050565b6000806000611427878788604001516117e2565b9050600061143a888889606001516117e2565b905060008660200151602001518361145291906122d5565b905060008760400151602001518361146a91906122d5565b9050600061147882846123d4565b90506000611487898584611889565b905060006114968a8585611889565b90508a6020015160200151826114ac91906123fd565b60408c0151602001516114bf90836123fd565b985098505050505050505094509492505050565b600080866001600160a01b03166332f85bbf6114f387600001518761189e565b6040516001600160e01b031960e084901b16815260048101919091526024810186905260606044820152602260648201527f496e76616c69642073746174652c206e6567617469766520706f6f6c416d6f756084820152611b9d60f21b60a482015260c4016020604051808303816000875af1158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b9190612310565b90506115aa8787878787611926565b50508451604051631daaefa160e01b81526001600160a01b03808916600483015291821660248201529085166044820152606481018490526084810182905273__$c1eebf06e53d0bd092f667687cf73e1ebf$__90631daaefa19060a40160006040518083038186803b15801561162057600080fd5b505af4158015611634573d6000803e3d6000fd5b50929998505050505050505050565b6000604051602001611684906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60008160016116dd82866123d4565b6116e791906122a6565b610c8091906123fd565b611749846323b872dd60e01b858585604051602401611712939291906122ec565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611aee565b50505050565b6000604051602001611684906020808252601b908201527a1513d5105317d4115391125391d7d253541050d517d05353d55395602a1b604082015260600190565b600080821215610cd9575060000390565b6000604051602001611684906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000806117f784604001518560600151611bc8565b905080856001600160a01b031663bd02d0f561181787600001518761189e565b6040518263ffffffff1660e01b815260040161183591815260200190565b602060405180830381865afa158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190612310565b61188091906123fd565b95945050505050565b6000611896848484611bf7565b949350505050565b60006040516020016118cf906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b6000806000876001600160a01b031663a6ed563e6119478860000151611ce1565b6040518263ffffffff1660e01b815260040161196591815260200190565b602060405180830381865afa158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a69190612310565b9050806119ba576000809250925050611ae4565b60006119c68787611d18565b90506000896001600160a01b0316638ca498b06119e38585611d90565b886040518363ffffffff1660e01b8152600401611a01929190612329565b6020604051808303816000875af1158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a449190612310565b885160405163a814bb6f60e01b81526001600160a01b03808d16600483015290911660248201528315156044820152606481018590526084810188905260a4810182905290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063a814bb6f9060c40160006040518083038186803b158015611ac257600080fd5b505af4158015611ad6573d6000803e3d6000fd5b506001975092955050505050505b9550959350505050565b6000611b43826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e029092919063ffffffff16565b9050805160001480611b64575080806020019051810190611b64919061241f565b611bc35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100d3565b505050565b6000816001600160a01b0316836001600160a01b031614611bea576001611bed565b60025b60ff169392505050565b6000808060001985870985870292508281108382030391505080600003611c3157838281611c2757611c276123e7565b0492505050610c80565b808411611c785760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016100d3565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001611684906020808252601190820152701592549515505317d3505492d15517d251607a1b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614158015611d56575082606001516001600160a01b0316826001600160a01b031614155b15611d7857825160405163785ee46960e01b81526100d3918491600401612002565b506040909101516001600160a01b0391821691161490565b6000604051602001611dd1906020808252601b908201527a5649525455414c5f494e56454e544f52595f464f525f535741505360281b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018490528215156060820152608001611908565b6060611896848460008585600080866001600160a01b03168587604051611e299190612465565b60006040518083038185875af1925050503d8060008114611e66576040519150601f19603f3d011682016040523d82523d6000602084013e611e6b565b606091505b5091509150611e7c87838387611e87565b979650505050505050565b60608315611ef6578251600003611eef576001600160a01b0385163b611eef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100d3565b5081611896565b6118968383815115611f0b5781518083602001fd5b8060405162461bcd60e51b81526004016100d39190612481565b6040518060600160405280611f38611f57565b8152602001611f45611f57565b8152602001611f52611f57565b905290565b604051806040016040528060008152602001600081525090565b6001600160a01b0381168114611f8657600080fd5b50565b60008060008060008060c08789031215611fa257600080fd5b8635611fad81611f71565b95506020870135611fbd81611f71565b94506040870135611fcd81611f71565b93506060870135611fdd81611f71565b92506080870135611fed81611f71565b8092505060a087013590509295509295509295565b6001600160a01b0392831681529116602082015260400190565b60405161018081016001600160401b038111828210171561204d57634e487b7160e01b600052604160045260246000fd5b60405290565b6000608082840312801561206657600080fd5b50604051608081016001600160401b038111828210171561209757634e487b7160e01b600052604160045260246000fd5b60405282516120a581611f71565b815260208301516120b581611f71565b602082015260408301516120c881611f71565b604082015260608301516120db81611f71565b60608201529392505050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b80518252602090810151910152565b6001600160a01b03858116825284166020820152610180810161214f60408301856120e7565b61215d60c08301845161211a565b602083015161217061010084018261211a565b50604083015161218461014084018261211a565b5095945050505050565b6001600160a01b03881681526101a081016121ac60208301896120e7565b6121b960a083018861211a565b6121c660e083018761211a565b6121d461012083018661211a565b8361016083015282151561018083015298975050505050505050565b600061018082840312801561220457600080fd5b50600061220f61201c565b835181526020808501519082015260408085015190820152606080850151908201526080808501519082015260a0808501519082015260c0808501519082015260e080850151908201526101008085015190820152610120808501519082015261014080850151908201526101609384015193810193909352509092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c0157610c01612290565b6000600160ff1b82016122ce576122ce612290565b5060000390565b8082028115828204841417610c0157610c01612290565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561232257600080fd5b5051919050565b918252602082015260400190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b0391909116815260200190565b6000604082840312801561238757600080fd5b506040805160009181016001600160401b03811182821017156123b857634e487b7160e01b83526041600452602483fd5b6040528351815260209384015193810193909352509092915050565b80820180821115610c0157610c01612290565b634e487b7160e01b600052601260045260246000fd5b60008261241a57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561243157600080fd5b81518015158114610c8057600080fd5b60005b8381101561245c578181015183820152602001612444565b50506000910152565b60008251612477818460208701612441565b9190910192915050565b60208152600082518060208401526124a0816040850160208701612441565b601f01601f1916919091016040019291505056fea26469706673582212201fffeaf6073b022864b42425218c2f1035cd51775570cec3491c6edc9bee7bb064736f6c634300081d0033", + "numDeployments": 4, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"poolValue\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"totalPendingImpactAmount\",\"type\":\"int256\"}],\"name\":\"InsufficientImpactPoolValueForWithdrawal\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"poolValue\",\"type\":\"int256\"}],\"name\":\"InvalidPoolValueForWithdrawal\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lentAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReductionAmount\",\"type\":\"uint256\"}],\"name\":\"ReductionExceedsLentAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"UnexpectedTokenForVirtualInventory\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/market/PositionImpactPoolUtils.sol\":\"PositionImpactPoolUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/market/PositionImpactPoolUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {Market} from \\\"./Market.sol\\\";\\nimport {MarketEventUtils} from \\\"./MarketEventUtils.sol\\\";\\nimport {MarketPoolValueInfo} from \\\"./MarketPoolValueInfo.sol\\\";\\nimport {MarketStoreUtils} from \\\"./MarketStoreUtils.sol\\\";\\nimport {MarketToken} from \\\"./MarketToken.sol\\\";\\nimport {MarketUtils} from \\\"./MarketUtils.sol\\\";\\nimport {SafeCast} from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IOracle } from \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../position/PositionUtils.sol\\\";\\n\\nlibrary PositionImpactPoolUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n using SafeERC20 for IERC20;\\n\\n using Market for Market.Props;\\n\\n // @dev withdraw funds from the position impact pool while maintaining GM token price\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param receiver the address to receive the withdrawn funds\\n // @param amount the amount to withdraw\\n // @param oracle - oracle to fetch the market prices\\n function withdrawFromPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n require(amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n MarketUtils.distributePositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market\\n );\\n\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\\n dataStore,\\n marketProps,\\n prices.indexTokenPrice,\\n prices.longTokenPrice,\\n prices.shortTokenPrice,\\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\\n false\\n );\\n\\n if (poolValueInfo.poolValue <= 0) {\\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\\n }\\n\\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\\n\\n // if there is a positive totalPendingImpactAmount, that means that the\\n // excess should be covered by the position impact pool, so subtract this\\n // from the impactPoolAmount that can be withdrawn\\n // lent amount is not considered here, because if there is a lent amount\\n // we assume that the position impact would be zero\\n if (totalPendingImpactAmount > 0) {\\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\\n }\\n\\n if (adjustedImpactPoolAmount < amount) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n MarketUtils.applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n - amount.toInt256()\\n );\\n\\n // Calculate amount of tokens to withdraw:\\n // We want to withdraw long and short tokens from the pool\\n // at the current pool token ratio\\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\\n dataStore,\\n marketProps,\\n prices,\\n amount * prices.indexTokenPrice.min\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n - longTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n - shortTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.longToken,\\n receiver,\\n longTokenWithdrawalAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.shortToken,\\n receiver,\\n shortTokenWithdrawalAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\\n eventEmitter,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external {\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\\n\\n if (reductionAmount > lentAmount) {\\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\\n }\\n\\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\\n\\n if (longTokenAmount > 0) {\\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\\n }\\n\\n if (shortTokenAmount > 0) {\\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\\n }\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n longTokenAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n shortTokenAmount.toInt256()\\n );\\n\\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitLentImpactAmountReduction(\\n eventEmitter,\\n market,\\n fundingAccount,\\n longTokenAmount,\\n shortTokenAmount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe74b2dfdd27d92eb33535d5c5fe4af456d05c180d17d8252f5728c62dd1293b0\",\"license\":\"BUSL-1.1\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0xa7a5a10c9321e7372bc6a8c11da319e6421ed5c0676810a1c8ec30c30f730331\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x6124ea610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631483c5fc146100455780639166d48114610067575b600080fd5b81801561005157600080fd5b50610065610060366004611f89565b610087565b005b81801561007357600080fd5b50610065610082366004611f89565b610666565b600081116100dc5760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e203000000060448201526064015b60405180910390fd5b60405163c468d13560e01b81526001600160a01b038088166004830152808716602483015284166044820152739080f8A35Da53F4200a68533FB1dC1cA05357bDB9063c468d1359060640160006040518083038186803b15801561013f57600080fd5b505af4158015610153573d6000803e3d6000fd5b505060405163a8d8fff560e01b815260009250732e5D10A48C00cFcc6A31af873118d739323Ff71B915063a8d8fff590610193908a908890600401612002565b608060405180830381865af41580156101b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d49190612053565b905060006101e28683610a8f565b604051631ce5b4e360e21b81529091507358b09FD12863218F2ca156808C2Ae48aaCD0c07290637396d38c90610222908b908b9087908790600401612129565b60006040518083038186803b15801561023a57600080fd5b505af415801561024e573d6000803e3d6000fd5b505050506000739080f8A35Da53F4200a68533FB1dC1cA05357bDB63f2e2a4f58a858560000151866020015187604001516040516020016102c0906020808252601e908201527f4d41585f504e4c5f464143544f525f464f525f5749544844524157414c530000604082015260600190565b6040516020818303038152906040528051906020012060006040518863ffffffff1660e01b81526004016102fa979695949392919061218e565b61018060405180830381865af4158015610318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033c91906121f0565b905060008160000151136103695780516040516390a6af3b60e01b815260048101919091526024016100d3565b610140810151600061037b8b89610c07565b905060008113156103dd5761038f81610c87565b8210156103c757610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6103d081610c87565b6103da90836122a6565b91505b8582101561041657610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6104338b8b8a6104258a610cdd565b61042e906122b9565b610d47565b6000806104558d88888960000151600001518c61045091906122d5565b611413565b9150915061047b8d8d898a6040015161046d87610cdd565b610476906122b9565b6114d3565b506104908d8d898a6060015161046d86610cdd565b50604080880151905163078d3b7960e01b81526001600160a01b038c169163078d3b79916104c591908d9087906004016122ec565b600060405180830381600087803b1580156104df57600080fd5b505af11580156104f3573d6000803e3d6000fd5b505050606088015160405163078d3b7960e01b81526001600160a01b038d16925063078d3b799161052a918d9086906004016122ec565b600060405180830381600087803b15801561054457600080fd5b505af1158015610558573d6000803e3d6000fd5b50505050739080f8A35Da53F4200a68533FB1dC1cA05357bDB635930015e8e8c6040518363ffffffff1660e01b8152600401610595929190612002565b60006040518083038186803b1580156105ad57600080fd5b505af41580156105c1573d6000803e3d6000fd5b5050604051635bb3aa7360e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89250635bb3aa739150610627908f908e908e908e906004016001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b60006040518083038186803b15801561063f57600080fd5b505af4158015610653573d6000803e3d6000fd5b5050505050505050505050505050505050565b60405163a8d8fff560e01b8152600090732e5D10A48C00cFcc6A31af873118d739323Ff71B9063a8d8fff5906106a2908a908890600401612002565b608060405180830381865af41580156106bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e39190612053565b905060006106f18683610a8f565b604051631ce5b4e360e21b81529091507358b09FD12863218F2ca156808C2Ae48aaCD0c07290637396d38c90610731908b908b9087908790600401612129565b60006040518083038186803b15801561074957600080fd5b505af415801561075d573d6000803e3d6000fd5b505050506000886001600160a01b031663bd02d0f561077b88611643565b6040518263ffffffff1660e01b815260040161079991815260200190565b602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190612310565b90508084111561080157808460405163eef4e17160e01b81526004016100d3929190612329565b81516020015160009061081490866122d5565b9050600061083682856020015160000151600261083191906122d5565b6116ce565b9050600061085383866040015160000151600261083191906122d5565b90508115610875576040860151610875906001600160a01b0316898b856116f1565b8015610895576060860151610895906001600160a01b0316898b846116f1565b6108a98c8c88896040015161047687610cdd565b506108be8c8c88896060015161047686610cdd565b5060008c6001600160a01b031663e98aabc16108d98c611643565b8a6040518363ffffffff1660e01b81526004016108f7929190612329565b6020604051808303816000875af1158015610916573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093a9190612310565b905073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8634ddb3d818d8c6109618c610cdd565b856040518563ffffffff1660e01b81526004016109819493929190612337565b60006040518083038186803b15801561099957600080fd5b505af41580156109ad573d6000803e3d6000fd5b50505050739080f8A35Da53F4200a68533FB1dC1cA05357bDB635930015e8e8c6040518363ffffffff1660e01b81526004016109ea929190612002565b60006040518083038186803b158015610a0257600080fd5b505af4158015610a16573d6000803e3d6000fd5b5050505073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c863850310d78d8c8c87878e6040518763ffffffff1660e01b8152600401610627969594939291906001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b610a97611f25565b6040518060600160405280846001600160a01b0316635dcf719485602001516040518263ffffffff1660e01b8152600401610ad29190612360565b6040805180830381865afa158015610aee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b129190612374565b8152602001846001600160a01b0316635dcf719485604001516040518263ffffffff1660e01b8152600401610b479190612360565b6040805180830381865afa158015610b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b879190612374565b8152602001846001600160a01b0316635dcf719485606001516040518263ffffffff1660e01b8152600401610bbc9190612360565b6040805180830381865afa158015610bd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfc9190612374565b905290505b92915050565b6000826001600160a01b031663dc97d962610c218461174f565b6040518263ffffffff1660e01b8152600401610c3f91815260200190565b602060405180830381865afa158015610c5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c809190612310565b9392505050565b600080821215610cd95760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016100d3565b5090565b60006001600160ff1b03821115610cd95760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016100d3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152610d8282611790565b604082015260008212156110dd57610d99836117a1565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015610de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e069190612310565b60608201819052604082015111156110275780606001518160400151610e2c91906122a6565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a91610e619190600090600401612329565b6020604051808303816000875af1158015610e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea49190612310565b5073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c863555a99798585610ece8560600151610cdd565b60006040518563ffffffff1660e01b8152600401610eef9493929190612337565b60006040518083038186803b158015610f0757600080fd5b505af4158015610f1b573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3610f3785611643565b83608001516040518363ffffffff1660e01b8152600401610f59929190612329565b6020604051808303816000875af1158015610f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9c9190612310565b8160a001818152505073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8634ddb3d818585610fce8560800151610cdd565b8560a001516040518563ffffffff1660e01b8152600401610ff29493929190612337565b60006040518083038186803b15801561100a57600080fd5b505af415801561101e573d6000803e3d6000fd5b5050505061140c565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261105892600401612329565b6020604051808303816000875af1158015611077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109b9190612310565b60a0820181905260405163555a997960e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89163555a997991610ff291889188918891600401612337565b6110e683611643565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190612310565b6060820181905260408201511115611322578060600151816040015161117d91906122a6565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a916111b59190600090600401612329565b6020604051808303816000875af11580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f89190612310565b5073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8634ddb3d8185856112228560600151610cdd565b60006040518563ffffffff1660e01b81526004016112439493929190612337565b60006040518083038186803b15801561125b57600080fd5b505af415801561126f573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab361128b856117a1565b83608001516040518363ffffffff1660e01b81526004016112ad929190612329565b6020604051808303816000875af11580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190612310565b8160a001818152505073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c863555a99798585610fce8560800151610cdd565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261135692600401612329565b6020604051808303816000875af1158015611375573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113999190612310565b60a08201819052604051634ddb3d8160e01b815273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c891634ddb3d81916113db91889188918891600401612337565b60006040518083038186803b1580156113f357600080fd5b505af4158015611407573d6000803e3d6000fd5b505050505b5050505050565b6000806000611427878788604001516117e2565b9050600061143a888889606001516117e2565b905060008660200151602001518361145291906122d5565b905060008760400151602001518361146a91906122d5565b9050600061147882846123d4565b90506000611487898584611889565b905060006114968a8585611889565b90508a6020015160200151826114ac91906123fd565b60408c0151602001516114bf90836123fd565b985098505050505050505094509492505050565b600080866001600160a01b03166332f85bbf6114f387600001518761189e565b6040516001600160e01b031960e084901b16815260048101919091526024810186905260606044820152602260648201527f496e76616c69642073746174652c206e6567617469766520706f6f6c416d6f756084820152611b9d60f21b60a482015260c4016020604051808303816000875af1158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b9190612310565b90506115aa8787878787611926565b50508451604051631daaefa160e01b81526001600160a01b03808916600483015291821660248201529085166044820152606481018490526084810182905273F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c890631daaefa19060a40160006040518083038186803b15801561162057600080fd5b505af4158015611634573d6000803e3d6000fd5b50929998505050505050505050565b6000604051602001611684906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60008160016116dd82866123d4565b6116e791906122a6565b610c8091906123fd565b611749846323b872dd60e01b858585604051602401611712939291906122ec565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611aee565b50505050565b6000604051602001611684906020808252601b908201527a1513d5105317d4115391125391d7d253541050d517d05353d55395602a1b604082015260600190565b600080821215610cd9575060000390565b6000604051602001611684906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000806117f784604001518560600151611bc8565b905080856001600160a01b031663bd02d0f561181787600001518761189e565b6040518263ffffffff1660e01b815260040161183591815260200190565b602060405180830381865afa158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190612310565b61188091906123fd565b95945050505050565b6000611896848484611bf7565b949350505050565b60006040516020016118cf906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b6000806000876001600160a01b031663a6ed563e6119478860000151611ce1565b6040518263ffffffff1660e01b815260040161196591815260200190565b602060405180830381865afa158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a69190612310565b9050806119ba576000809250925050611ae4565b60006119c68787611d18565b90506000896001600160a01b0316638ca498b06119e38585611d90565b886040518363ffffffff1660e01b8152600401611a01929190612329565b6020604051808303816000875af1158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a449190612310565b885160405163a814bb6f60e01b81526001600160a01b03808d16600483015290911660248201528315156044820152606481018590526084810188905260a4810182905290915073F6e667bD3C914A336aFB57C38ABbF6ef41e2e7c89063a814bb6f9060c40160006040518083038186803b158015611ac257600080fd5b505af4158015611ad6573d6000803e3d6000fd5b506001975092955050505050505b9550959350505050565b6000611b43826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e029092919063ffffffff16565b9050805160001480611b64575080806020019051810190611b64919061241f565b611bc35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100d3565b505050565b6000816001600160a01b0316836001600160a01b031614611bea576001611bed565b60025b60ff169392505050565b6000808060001985870985870292508281108382030391505080600003611c3157838281611c2757611c276123e7565b0492505050610c80565b808411611c785760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016100d3565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001611684906020808252601190820152701592549515505317d3505492d15517d251607a1b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614158015611d56575082606001516001600160a01b0316826001600160a01b031614155b15611d7857825160405163785ee46960e01b81526100d3918491600401612002565b506040909101516001600160a01b0391821691161490565b6000604051602001611dd1906020808252601b908201527a5649525455414c5f494e56454e544f52595f464f525f535741505360281b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018490528215156060820152608001611908565b6060611896848460008585600080866001600160a01b03168587604051611e299190612465565b60006040518083038185875af1925050503d8060008114611e66576040519150601f19603f3d011682016040523d82523d6000602084013e611e6b565b606091505b5091509150611e7c87838387611e87565b979650505050505050565b60608315611ef6578251600003611eef576001600160a01b0385163b611eef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100d3565b5081611896565b6118968383815115611f0b5781518083602001fd5b8060405162461bcd60e51b81526004016100d39190612481565b6040518060600160405280611f38611f57565b8152602001611f45611f57565b8152602001611f52611f57565b905290565b604051806040016040528060008152602001600081525090565b6001600160a01b0381168114611f8657600080fd5b50565b60008060008060008060c08789031215611fa257600080fd5b8635611fad81611f71565b95506020870135611fbd81611f71565b94506040870135611fcd81611f71565b93506060870135611fdd81611f71565b92506080870135611fed81611f71565b8092505060a087013590509295509295509295565b6001600160a01b0392831681529116602082015260400190565b60405161018081016001600160401b038111828210171561204d57634e487b7160e01b600052604160045260246000fd5b60405290565b6000608082840312801561206657600080fd5b50604051608081016001600160401b038111828210171561209757634e487b7160e01b600052604160045260246000fd5b60405282516120a581611f71565b815260208301516120b581611f71565b602082015260408301516120c881611f71565b604082015260608301516120db81611f71565b60608201529392505050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b80518252602090810151910152565b6001600160a01b03858116825284166020820152610180810161214f60408301856120e7565b61215d60c08301845161211a565b602083015161217061010084018261211a565b50604083015161218461014084018261211a565b5095945050505050565b6001600160a01b03881681526101a081016121ac60208301896120e7565b6121b960a083018861211a565b6121c660e083018761211a565b6121d461012083018661211a565b8361016083015282151561018083015298975050505050505050565b600061018082840312801561220457600080fd5b50600061220f61201c565b835181526020808501519082015260408085015190820152606080850151908201526080808501519082015260a0808501519082015260c0808501519082015260e080850151908201526101008085015190820152610120808501519082015261014080850151908201526101609384015193810193909352509092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c0157610c01612290565b6000600160ff1b82016122ce576122ce612290565b5060000390565b8082028115828204841417610c0157610c01612290565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561232257600080fd5b5051919050565b918252602082015260400190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b0391909116815260200190565b6000604082840312801561238757600080fd5b506040805160009181016001600160401b03811182821017156123b857634e487b7160e01b83526041600452602483fd5b6040528351815260209384015193810193909352509092915050565b80820180821115610c0157610c01612290565b634e487b7160e01b600052601260045260246000fd5b60008261241a57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561243157600080fd5b81518015158114610c8057600080fd5b60005b8381101561245c578181015183820152602001612444565b50506000910152565b60008251612477818460208701612441565b9190910192915050565b60208152600082518060208401526124a0816040850160208701612441565b601f01601f1916919091016040019291505056fea264697066735822122057df7e51015c57dc7aca526eec25e7655497f764c1ba23f85e30730146c8fc7c64736f6c634300081d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631483c5fc146100455780639166d48114610067575b600080fd5b81801561005157600080fd5b50610065610060366004611f89565b610087565b005b81801561007357600080fd5b50610065610082366004611f89565b610666565b600081116100dc5760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e203000000060448201526064015b60405180910390fd5b60405163c468d13560e01b81526001600160a01b03808816600483015280871660248301528416604482015273__$e53db83827f4e07ebc418caf7145b8c2d5$__9063c468d1359060640160006040518083038186803b15801561013f57600080fd5b505af4158015610153573d6000803e3d6000fd5b505060405163a8d8fff560e01b81526000925073__$ff439aa65a80c9eec648f15db20b189505$__915063a8d8fff590610193908a908890600401612002565b608060405180830381865af41580156101b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d49190612053565b905060006101e28683610a8f565b604051631ce5b4e360e21b815290915073__$91a1a7f12f728c8759f4be979bae55555f$__90637396d38c90610222908b908b9087908790600401612129565b60006040518083038186803b15801561023a57600080fd5b505af415801561024e573d6000803e3d6000fd5b50505050600073__$e53db83827f4e07ebc418caf7145b8c2d5$__63f2e2a4f58a858560000151866020015187604001516040516020016102c0906020808252601e908201527f4d41585f504e4c5f464143544f525f464f525f5749544844524157414c530000604082015260600190565b6040516020818303038152906040528051906020012060006040518863ffffffff1660e01b81526004016102fa979695949392919061218e565b61018060405180830381865af4158015610318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033c91906121f0565b905060008160000151136103695780516040516390a6af3b60e01b815260048101919091526024016100d3565b610140810151600061037b8b89610c07565b905060008113156103dd5761038f81610c87565b8210156103c757610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6103d081610c87565b6103da90836122a6565b91505b8582101561041657610140830151604051634321e90560e11b8152600481018890526024810191909152604481018290526064016100d3565b6104338b8b8a6104258a610cdd565b61042e906122b9565b610d47565b6000806104558d88888960000151600001518c61045091906122d5565b611413565b9150915061047b8d8d898a6040015161046d87610cdd565b610476906122b9565b6114d3565b506104908d8d898a6060015161046d86610cdd565b50604080880151905163078d3b7960e01b81526001600160a01b038c169163078d3b79916104c591908d9087906004016122ec565b600060405180830381600087803b1580156104df57600080fd5b505af11580156104f3573d6000803e3d6000fd5b505050606088015160405163078d3b7960e01b81526001600160a01b038d16925063078d3b799161052a918d9086906004016122ec565b600060405180830381600087803b15801561054457600080fd5b505af1158015610558573d6000803e3d6000fd5b5050505073__$e53db83827f4e07ebc418caf7145b8c2d5$__635930015e8e8c6040518363ffffffff1660e01b8152600401610595929190612002565b60006040518083038186803b1580156105ad57600080fd5b505af41580156105c1573d6000803e3d6000fd5b5050604051635bb3aa7360e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9250635bb3aa739150610627908f908e908e908e906004016001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b60006040518083038186803b15801561063f57600080fd5b505af4158015610653573d6000803e3d6000fd5b5050505050505050505050505050505050565b60405163a8d8fff560e01b815260009073__$ff439aa65a80c9eec648f15db20b189505$__9063a8d8fff5906106a2908a908890600401612002565b608060405180830381865af41580156106bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e39190612053565b905060006106f18683610a8f565b604051631ce5b4e360e21b815290915073__$91a1a7f12f728c8759f4be979bae55555f$__90637396d38c90610731908b908b9087908790600401612129565b60006040518083038186803b15801561074957600080fd5b505af415801561075d573d6000803e3d6000fd5b505050506000886001600160a01b031663bd02d0f561077b88611643565b6040518263ffffffff1660e01b815260040161079991815260200190565b602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190612310565b90508084111561080157808460405163eef4e17160e01b81526004016100d3929190612329565b81516020015160009061081490866122d5565b9050600061083682856020015160000151600261083191906122d5565b6116ce565b9050600061085383866040015160000151600261083191906122d5565b90508115610875576040860151610875906001600160a01b0316898b856116f1565b8015610895576060860151610895906001600160a01b0316898b846116f1565b6108a98c8c88896040015161047687610cdd565b506108be8c8c88896060015161047686610cdd565b5060008c6001600160a01b031663e98aabc16108d98c611643565b8a6040518363ffffffff1660e01b81526004016108f7929190612329565b6020604051808303816000875af1158015610916573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093a9190612310565b905073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818d8c6109618c610cdd565b856040518563ffffffff1660e01b81526004016109819493929190612337565b60006040518083038186803b15801561099957600080fd5b505af41580156109ad573d6000803e3d6000fd5b5050505073__$e53db83827f4e07ebc418caf7145b8c2d5$__635930015e8e8c6040518363ffffffff1660e01b81526004016109ea929190612002565b60006040518083038186803b158015610a0257600080fd5b505af4158015610a16573d6000803e3d6000fd5b5050505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63850310d78d8c8c87878e6040518763ffffffff1660e01b8152600401610627969594939291906001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b610a97611f25565b6040518060600160405280846001600160a01b0316635dcf719485602001516040518263ffffffff1660e01b8152600401610ad29190612360565b6040805180830381865afa158015610aee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b129190612374565b8152602001846001600160a01b0316635dcf719485604001516040518263ffffffff1660e01b8152600401610b479190612360565b6040805180830381865afa158015610b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b879190612374565b8152602001846001600160a01b0316635dcf719485606001516040518263ffffffff1660e01b8152600401610bbc9190612360565b6040805180830381865afa158015610bd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfc9190612374565b905290505b92915050565b6000826001600160a01b031663dc97d962610c218461174f565b6040518263ffffffff1660e01b8152600401610c3f91815260200190565b602060405180830381865afa158015610c5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c809190612310565b9392505050565b600080821215610cd95760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016100d3565b5090565b60006001600160ff1b03821115610cd95760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016100d3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152610d8282611790565b604082015260008212156110dd57610d99836117a1565b80825260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015610de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e069190612310565b60608201819052604082015111156110275780606001518160400151610e2c91906122a6565b60808201528051604051637152429d60e11b81526001600160a01b0387169163e2a4853a91610e619190600090600401612329565b6020604051808303816000875af1158015610e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea49190612310565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585610ece8560600151610cdd565b60006040518563ffffffff1660e01b8152600401610eef9493929190612337565b60006040518083038186803b158015610f0757600080fd5b505af4158015610f1b573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab3610f3785611643565b83608001516040518363ffffffff1660e01b8152600401610f59929190612329565b6020604051808303816000875af1158015610f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9c9190612310565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d818585610fce8560800151610cdd565b8560a001516040518563ffffffff1660e01b8152600401610ff29493929190612337565b60006040518083038186803b15801561100a57600080fd5b505af415801561101e573d6000803e3d6000fd5b5050505061140c565b8051604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261105892600401612329565b6020604051808303816000875af1158015611077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109b9190612310565b60a0820181905260405163555a997960e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__9163555a997991610ff291889188918891600401612337565b6110e683611643565b6020820181905260405163bd02d0f560e01b815260048101919091526001600160a01b0386169063bd02d0f590602401602060405180830381865afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190612310565b6060820181905260408201511115611322578060600151816040015161117d91906122a6565b60808201526020810151604051637152429d60e11b81526001600160a01b0387169163e2a4853a916111b59190600090600401612329565b6020604051808303816000875af11580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f89190612310565b5073__$c1eebf06e53d0bd092f667687cf73e1ebf$__634ddb3d8185856112228560600151610cdd565b60006040518563ffffffff1660e01b81526004016112439493929190612337565b60006040518083038186803b15801561125b57600080fd5b505af415801561126f573d6000803e3d6000fd5b50505050846001600160a01b031663340dbab361128b856117a1565b83608001516040518363ffffffff1660e01b81526004016112ad929190612329565b6020604051808303816000875af11580156112cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f09190612310565b8160a001818152505073__$c1eebf06e53d0bd092f667687cf73e1ebf$__63555a99798585610fce8560800151610cdd565b6020810151604080830151905163e98aabc160e01b81526001600160a01b0388169263e98aabc19261135692600401612329565b6020604051808303816000875af1158015611375573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113999190612310565b60a08201819052604051634ddb3d8160e01b815273__$c1eebf06e53d0bd092f667687cf73e1ebf$__91634ddb3d81916113db91889188918891600401612337565b60006040518083038186803b1580156113f357600080fd5b505af4158015611407573d6000803e3d6000fd5b505050505b5050505050565b6000806000611427878788604001516117e2565b9050600061143a888889606001516117e2565b905060008660200151602001518361145291906122d5565b905060008760400151602001518361146a91906122d5565b9050600061147882846123d4565b90506000611487898584611889565b905060006114968a8585611889565b90508a6020015160200151826114ac91906123fd565b60408c0151602001516114bf90836123fd565b985098505050505050505094509492505050565b600080866001600160a01b03166332f85bbf6114f387600001518761189e565b6040516001600160e01b031960e084901b16815260048101919091526024810186905260606044820152602260648201527f496e76616c69642073746174652c206e6567617469766520706f6f6c416d6f756084820152611b9d60f21b60a482015260c4016020604051808303816000875af1158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b9190612310565b90506115aa8787878787611926565b50508451604051631daaefa160e01b81526001600160a01b03808916600483015291821660248201529085166044820152606481018490526084810182905273__$c1eebf06e53d0bd092f667687cf73e1ebf$__90631daaefa19060a40160006040518083038186803b15801561162057600080fd5b505af4158015611634573d6000803e3d6000fd5b50929998505050505050505050565b6000604051602001611684906020808252818101527f4c454e545f504f534954494f4e5f494d504143545f504f4f4c5f414d4f554e54604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03841690820152606001604051602081830303815290604052805190602001209050919050565b60008160016116dd82866123d4565b6116e791906122a6565b610c8091906123fd565b611749846323b872dd60e01b858585604051602401611712939291906122ec565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611aee565b50505050565b6000604051602001611684906020808252601b908201527a1513d5105317d4115391125391d7d253541050d517d05353d55395602a1b604082015260600190565b600080821215610cd9575060000390565b6000604051602001611684906020808252601b908201527a1413d4d2551253d397d253541050d517d413d3d317d05353d55395602a1b604082015260600190565b6000806117f784604001518560600151611bc8565b905080856001600160a01b031663bd02d0f561181787600001518761189e565b6040518263ffffffff1660e01b815260040161183591815260200190565b602060405180830381865afa158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190612310565b61188091906123fd565b95945050505050565b6000611896848484611bf7565b949350505050565b60006040516020016118cf906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b6000806000876001600160a01b031663a6ed563e6119478860000151611ce1565b6040518263ffffffff1660e01b815260040161196591815260200190565b602060405180830381865afa158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a69190612310565b9050806119ba576000809250925050611ae4565b60006119c68787611d18565b90506000896001600160a01b0316638ca498b06119e38585611d90565b886040518363ffffffff1660e01b8152600401611a01929190612329565b6020604051808303816000875af1158015611a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a449190612310565b885160405163a814bb6f60e01b81526001600160a01b03808d16600483015290911660248201528315156044820152606481018590526084810188905260a4810182905290915073__$c1eebf06e53d0bd092f667687cf73e1ebf$__9063a814bb6f9060c40160006040518083038186803b158015611ac257600080fd5b505af4158015611ad6573d6000803e3d6000fd5b506001975092955050505050505b9550959350505050565b6000611b43826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e029092919063ffffffff16565b9050805160001480611b64575080806020019051810190611b64919061241f565b611bc35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100d3565b505050565b6000816001600160a01b0316836001600160a01b031614611bea576001611bed565b60025b60ff169392505050565b6000808060001985870985870292508281108382030391505080600003611c3157838281611c2757611c276123e7565b0492505050610c80565b808411611c785760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016100d3565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000604051602001611684906020808252601190820152701592549515505317d3505492d15517d251607a1b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614158015611d56575082606001516001600160a01b0316826001600160a01b031614155b15611d7857825160405163785ee46960e01b81526100d3918491600401612002565b506040909101516001600160a01b0391821691161490565b6000604051602001611dd1906020808252601b908201527a5649525455414c5f494e56454e544f52595f464f525f535741505360281b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018490528215156060820152608001611908565b6060611896848460008585600080866001600160a01b03168587604051611e299190612465565b60006040518083038185875af1925050503d8060008114611e66576040519150601f19603f3d011682016040523d82523d6000602084013e611e6b565b606091505b5091509150611e7c87838387611e87565b979650505050505050565b60608315611ef6578251600003611eef576001600160a01b0385163b611eef5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100d3565b5081611896565b6118968383815115611f0b5781518083602001fd5b8060405162461bcd60e51b81526004016100d39190612481565b6040518060600160405280611f38611f57565b8152602001611f45611f57565b8152602001611f52611f57565b905290565b604051806040016040528060008152602001600081525090565b6001600160a01b0381168114611f8657600080fd5b50565b60008060008060008060c08789031215611fa257600080fd5b8635611fad81611f71565b95506020870135611fbd81611f71565b94506040870135611fcd81611f71565b93506060870135611fdd81611f71565b92506080870135611fed81611f71565b8092505060a087013590509295509295509295565b6001600160a01b0392831681529116602082015260400190565b60405161018081016001600160401b038111828210171561204d57634e487b7160e01b600052604160045260246000fd5b60405290565b6000608082840312801561206657600080fd5b50604051608081016001600160401b038111828210171561209757634e487b7160e01b600052604160045260246000fd5b60405282516120a581611f71565b815260208301516120b581611f71565b602082015260408301516120c881611f71565b604082015260608301516120db81611f71565b60608201529392505050565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b80518252602090810151910152565b6001600160a01b03858116825284166020820152610180810161214f60408301856120e7565b61215d60c08301845161211a565b602083015161217061010084018261211a565b50604083015161218461014084018261211a565b5095945050505050565b6001600160a01b03881681526101a081016121ac60208301896120e7565b6121b960a083018861211a565b6121c660e083018761211a565b6121d461012083018661211a565b8361016083015282151561018083015298975050505050505050565b600061018082840312801561220457600080fd5b50600061220f61201c565b835181526020808501519082015260408085015190820152606080850151908201526080808501519082015260a0808501519082015260c0808501519082015260e080850151908201526101008085015190820152610120808501519082015261014080850151908201526101609384015193810193909352509092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c0157610c01612290565b6000600160ff1b82016122ce576122ce612290565b5060000390565b8082028115828204841417610c0157610c01612290565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561232257600080fd5b5051919050565b918252602082015260400190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b0391909116815260200190565b6000604082840312801561238757600080fd5b506040805160009181016001600160401b03811182821017156123b857634e487b7160e01b83526041600452602483fd5b6040528351815260209384015193810193909352509092915050565b80820180821115610c0157610c01612290565b634e487b7160e01b600052601260045260246000fd5b60008261241a57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561243157600080fd5b81518015158114610c8057600080fd5b60005b8381101561245c578181015183820152602001612444565b50506000910152565b60008251612477818460208701612441565b9190910192915050565b60208152600082518060208401526124a0816040850160208701612441565b601f01601f1916919091016040019291505056fea264697066735822122057df7e51015c57dc7aca526eec25e7655497f764c1ba23f85e30730146c8fc7c64736f6c634300081d0033", "libraries": { - "MarketUtils": "0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96", - "MarketEventUtils": "0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8", - "MarketStoreUtils": "0xd727120ac811e9136D4a5D5C6219aEE37e275785", - "PositionUtils": "0xf718aE0025504577b18f8773e56986B6e29C819F" + "MarketUtils": "0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB", + "MarketEventUtils": "0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8", + "MarketStoreUtils": "0x2e5D10A48C00cFcc6A31af873118d739323Ff71B", + "PositionUtils": "0x58b09FD12863218F2ca156808C2Ae48aaCD0c072" }, "devdoc": { "kind": "dev", diff --git a/deployments/arbitrum/PositionPricingUtils.json b/deployments/arbitrum/PositionPricingUtils.json index 437ff137f..55a89f8ff 100644 --- a/deployments/arbitrum/PositionPricingUtils.json +++ b/deployments/arbitrum/PositionPricingUtils.json @@ -1,28 +1,28 @@ { - "address": "0x984Eada4e97CDA510B48BB654A216d3ad47bA362", + "address": "0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4", "abi": [], - "transactionHash": "0x846ea90ee51e486bb6f4194abcfc75a2b2ff386dfe5f147be50aa3bc483618bd", + "transactionHash": "0xf4895e2f9d9a610c04a246db953aee1d80cf2dbc87ad11bc9c863d40a1f4c7e8", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0x984Eada4e97CDA510B48BB654A216d3ad47bA362", - "transactionIndex": 2, - "gasUsed": "74630", + "contractAddress": "0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4", + "transactionIndex": 4, + "gasUsed": "73614", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xac49095997226b9a17ec9878ef07cf806837547cd353869c0e50dfdc6554e4e6", - "transactionHash": "0x846ea90ee51e486bb6f4194abcfc75a2b2ff386dfe5f147be50aa3bc483618bd", + "blockHash": "0x507d8a629e7a08aba54d04000ca4da9e2d97a32714d6adb5a3fb459bbcd412c2", + "transactionHash": "0xf4895e2f9d9a610c04a246db953aee1d80cf2dbc87ad11bc9c863d40a1f4c7e8", "logs": [], - "blockNumber": 367562522, - "cumulativeGasUsed": "132504", + "blockNumber": 390053910, + "cumulativeGasUsed": "348504", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 24, - "solcInputHash": "79ca35a0eb57a5a4e0af2a0fc5a1dbeb", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/pricing/PositionPricingUtils.sol\":\"PositionPricingUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122079e2d9423ada7af9379888f5413e4a93da56d3e1e8ec45abf43acb1f091960f864736f6c634300081d0033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122079e2d9423ada7af9379888f5413e4a93da56d3e1e8ec45abf43acb1f091960f864736f6c634300081d0033", + "numDeployments": 25, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/pricing/PositionPricingUtils.sol\":\"PositionPricingUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122064db7d7c38a76c4174dca63c2deca19554c3bc7272a25fb80654d0485bf4bf6064736f6c634300081d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122064db7d7c38a76c4174dca63c2deca19554c3bc7272a25fb80654d0485bf4bf6064736f6c634300081d0033", "libraries": {}, "devdoc": { "kind": "dev", diff --git a/deployments/arbitrum/PositionUtils.json b/deployments/arbitrum/PositionUtils.json index 988c17d1a..7728f2025 100644 --- a/deployments/arbitrum/PositionUtils.json +++ b/deployments/arbitrum/PositionUtils.json @@ -1,5 +1,5 @@ { - "address": "0xf718aE0025504577b18f8773e56986B6e29C819F", + "address": "0x58b09FD12863218F2ca156808C2Ae48aaCD0c072", "abi": [ { "inputs": [], @@ -1876,32 +1876,32 @@ "type": "function" } ], - "transactionHash": "0x7db918e762d085fb6dc2e50ea33735bfbbd6794c09ad68a43843e4d656c651bc", + "transactionHash": "0x57949e08920bc261234b0ced9dcba3cec73e88f29f92d4ec2219fc4f683e1ce5", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0xf718aE0025504577b18f8773e56986B6e29C819F", + "contractAddress": "0x58b09FD12863218F2ca156808C2Ae48aaCD0c072", "transactionIndex": 3, - "gasUsed": "5027523", + "gasUsed": "4979630", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x38311d358c23db649f5b7670ca075f76bf829247b8d0e540848297156aeac9b0", - "transactionHash": "0x7db918e762d085fb6dc2e50ea33735bfbbd6794c09ad68a43843e4d656c651bc", + "blockHash": "0xcd488802e35b14d197acd095a61e2ffac5836de45d9b2e4a455e8311b21371e5", + "transactionHash": "0x57949e08920bc261234b0ced9dcba3cec73e88f29f92d4ec2219fc4f683e1ce5", "logs": [], - "blockNumber": 367562536, - "cumulativeGasUsed": "5376621", + "blockNumber": 390053925, + "cumulativeGasUsed": "5105967", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 24, - "solcInputHash": "79ca35a0eb57a5a4e0af2a0fc5a1dbeb", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"EmptySizeDeltaInTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidCollateralTokenForMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"}],\"name\":\"InvalidPositionSizeValues\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"int256\",\"name\":\"remainingCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsdForLeverage\",\"type\":\"int256\"}],\"name\":\"LiquidatablePosition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"positionSizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minPositionSizeUsd\",\"type\":\"uint256\"}],\"name\":\"MinPositionSize\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"executionPrice\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"positionSizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"priceImpactUsd\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"}],\"name\":\"NegativeExecutionPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"acceptablePrice\",\"type\":\"uint256\"}],\"name\":\"OrderNotFulfillableAtAcceptablePrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__Exp2InputTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__LogInputTooSmall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivFixedPointOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"priceImpactUsd\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"}],\"name\":\"PriceImpactLargerThanOrderSize\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"UnableToGetCachedTokenPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"positionBorrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cumulativeBorrowingFactor\",\"type\":\"uint256\"}],\"name\":\"UnexpectedBorrowingFactor\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"usdDelta\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"longOpenInterest\",\"type\":\"uint256\"}],\"name\":\"UsdDeltaExceedsLongOpenInterest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"usdDelta\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"shortOpenInterest\",\"type\":\"uint256\"}],\"name\":\"UsdDeltaExceedsShortOpenInterest\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"eventEmitter\",\"type\":\"EventEmitter\"},{\"internalType\":\"contract MultichainVault\",\"name\":\"multichainVault\",\"type\":\"MultichainVault\"},{\"internalType\":\"contract OrderVault\",\"name\":\"orderVault\",\"type\":\"OrderVault\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"IOracle\"},{\"internalType\":\"contract ISwapHandler\",\"name\":\"swapHandler\",\"type\":\"ISwapHandler\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"}],\"internalType\":\"struct BaseOrderUtils.ExecuteOrderParamsContracts\",\"name\":\"contracts\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cancellationReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"callbackContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"uiFeeReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialCollateralToken\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"internalType\":\"struct Order.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"enum Order.OrderType\",\"name\":\"orderType\",\"type\":\"Order.OrderType\"},{\"internalType\":\"enum Order.DecreasePositionSwapType\",\"name\":\"decreasePositionSwapType\",\"type\":\"Order.DecreasePositionSwapType\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialCollateralDeltaAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"triggerPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"acceptablePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callbackGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"validFromTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"}],\"internalType\":\"struct Order.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"shouldUnwrapNativeToken\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isFrozen\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"autoCancel\",\"type\":\"bool\"}],\"internalType\":\"struct Order.Flags\",\"name\":\"flags\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"_dataList\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct Order.Props\",\"name\":\"order\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"orderKey\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"positionKey\",\"type\":\"bytes32\"},{\"internalType\":\"enum Order.SecondaryOrderType\",\"name\":\"secondaryOrderType\",\"type\":\"Order.SecondaryOrderType\"}],\"internalType\":\"struct PositionUtils.UpdatePositionParams\",\"name\":\"params\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"}],\"name\":\"getExecutionPriceForDecrease\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"eventEmitter\",\"type\":\"EventEmitter\"},{\"internalType\":\"contract MultichainVault\",\"name\":\"multichainVault\",\"type\":\"MultichainVault\"},{\"internalType\":\"contract OrderVault\",\"name\":\"orderVault\",\"type\":\"OrderVault\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"IOracle\"},{\"internalType\":\"contract ISwapHandler\",\"name\":\"swapHandler\",\"type\":\"ISwapHandler\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"}],\"internalType\":\"struct BaseOrderUtils.ExecuteOrderParamsContracts\",\"name\":\"contracts\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cancellationReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"callbackContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"uiFeeReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialCollateralToken\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"internalType\":\"struct Order.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"enum Order.OrderType\",\"name\":\"orderType\",\"type\":\"Order.OrderType\"},{\"internalType\":\"enum Order.DecreasePositionSwapType\",\"name\":\"decreasePositionSwapType\",\"type\":\"Order.DecreasePositionSwapType\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialCollateralDeltaAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"triggerPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"acceptablePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callbackGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"validFromTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"}],\"internalType\":\"struct Order.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"shouldUnwrapNativeToken\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isFrozen\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"autoCancel\",\"type\":\"bool\"}],\"internalType\":\"struct Order.Flags\",\"name\":\"flags\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"_dataList\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct Order.Props\",\"name\":\"order\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"orderKey\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"positionKey\",\"type\":\"bytes32\"},{\"internalType\":\"enum Order.SecondaryOrderType\",\"name\":\"secondaryOrderType\",\"type\":\"Order.SecondaryOrderType\"}],\"internalType\":\"struct PositionUtils.UpdatePositionParams\",\"name\":\"params\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"}],\"name\":\"getExecutionPriceForIncrease\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"}],\"name\":\"getPositionPnlUsd\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"shouldValidateMinCollateralUsd\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"forLiquidation\",\"type\":\"bool\"}],\"name\":\"isPositionLiquidatable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"remainingCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsdForLeverage\",\"type\":\"int256\"}],\"internalType\":\"struct PositionUtils.IsPositionLiquidatableInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"shouldValidateMinPositionSize\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"shouldValidateMinCollateralUsd\",\"type\":\"bool\"}],\"name\":\"validatePosition\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"positionSizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"positionCollateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"realizedPnlUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"openInterestDelta\",\"type\":\"int256\"}],\"internalType\":\"struct PositionUtils.WillPositionCollateralBeSufficientValues\",\"name\":\"values\",\"type\":\"tuple\"}],\"name\":\"willPositionCollateralBeSufficient\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMathUD60x18__Exp2InputTooBig(uint256)\":[{\"notice\":\"Emitted when the input is greater than 192.\"}],\"PRBMathUD60x18__LogInputTooSmall(uint256)\":[{\"notice\":\"Emitted when the input is less than 1.\"}],\"PRBMath__MulDivFixedPointOverflow(uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/position/PositionUtils.sol\":\"PositionUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n // @dev IsPositionLiquidatableCache struct used in isPositionLiquidatable\\n // to avoid stack too deep errors\\n // @param positionPnlUsd the position's pnl in USD\\n // @param minCollateralFactor the min collateral factor\\n // @param collateralTokenPrice the collateral token price\\n // @param collateralUsd the position's collateral in USD\\n // @param usdDeltaForPriceImpact the usdDelta value for the price impact calculation\\n // @param priceImpactUsd the price impact of closing the position in USD\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n // @dev check if a position is liquidatable\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0x98416c7f41b0baf01552655c8034e98c71f204b6449fa967c44eb2df84391fab\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x6157eb610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100775760003560e01c8063610e3cb91461007c5780637396d38c146100be57806381db61b8146100e0578063a6dcd97614610110578063d7e3321114610132578063dac6485714610145578063e22de7931461016f575b600080fd5b61008f61008a366004615182565b61019d565b6040805195865260208601949094529284019190915260608301521515608082015260a0015b60405180910390f35b8180156100ca57600080fd5b506100de6100d93660046151d0565b61045a565b005b6100f36100ee36600461522b565b6105ad565b6040805193845260208401929092521515908201526060016100b5565b61012361011e366004615270565b6106f5565b6040516100b593929190615348565b6100de610140366004615270565b610bbf565b610158610153366004615388565b610dd7565b6040805192151583526020830191909152016100b5565b61018261017d366004615441565b610ea3565b604080519384526020840192909252908201526060016100b5565b60008060008060006101b88760400151602001516040015190565b6000036101f05760008060006101df6101d78b60800151604001515190565b8a5190611203565b600094509450945094509450610450565b6102246040518060a00160405280600081526020016000815260200160008152602001600015158152602001600081525090565b604080516080810182528951516001600160a01b031681526020808b0151818301528a83015101518201516102829282019061026490611220565b611220565b81526020016102798b60400151604001515190565b1515905261128e565b1515606083015280825288515160208a01515160408b01516102b393906102ae90602001516040015190565b61134c565b808252600012156102e3578651602001516102cd90611220565b81516102d991906154d1565b60208201526102f8565b80518751516102f29190611398565b60208201525b608088015160400151511561033557865160200151604089015161032190602001516040015190565b61032b91906154ff565b6040820152610359565b61035361034b8960400151602001516040015190565b88515161140c565b60408201525b600061036b8960800151604001515190565b156103935781602001516103828360400151611220565b61038c9190615513565b90506103b2565b81602001516103a58360400151611220565b6103af919061553b565b90505b60008112156103ed57815160408a8101516020015101516040516378320e4960e11b81526004016103e4929190615562565b60405180910390fd5b6104286104038a60400151602001516040015190565b61040c8361142f565b60408c01516020015160a0015160808d01516040015151611481565b6080830181905282516020840151604085015160609095015191995097509295509350909150505b9295509295909350565b60405163034aadf760e61b815273F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d969063d2ab7dc0906104979087908790879087906004016155e6565b60006040518083038186803b1580156104af57600080fd5b505af41580156104c3573d6000803e3d6000fd5b5050604051631450a87960e01b815273F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d969250631450a8799150610507908790879087908790600190600401615619565b60006040518083038186803b15801561051f57600080fd5b505af4158015610533573d6000803e3d6000fd5b5050604051631450a87960e01b815273F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d969250631450a8799150610577908790879087908790600090600401615619565b60006040518083038186803b15801561058f57600080fd5b505af41580156105a3573d6000803e3d6000fd5b5050505050505050565b6000806000806105c68660400151602001516040015190565b9050806000036105fb5760006105ed6105e58860800151604001515190565b879015611203565b6000935093509350506106ee565b610621604051806060016040528060008152602001600015158152602001600081525090565b604080516080810182528851516001600160a01b031681526020808a01519082015261067091810161065285611220565b61065b9061565f565b81526020016102798a60400151604001515190565b1515602080840191909152818352885151908901515160408a015161069f93906102ae90602001516040015190565b80825260808801516020808201518051908201516040808d01519093015160a001519290930151516106d6948b94929388926114fc565b60408201819052815160209092015191955093509150505b9250925092565b600060606107016146f9565b61070961471a565b6107116146f9565b6107248c8a8a8d61017d8f602001515190565b5050825261073e6107378b516040015190565b8a8a6116ad565b60408301819052516107558b602001516040015190565b61075f919061567b565b606083015261077361025f8b602001515190565b61077c9061565f565b8260800181815250506107be60405180608001604052808e6001600160a01b031681526020018b8152602001846080015181526020016102798d604001515190565b151560c084015260a08301819052895160208c0151516107e0928f929161134c565b60a083015260006107f68b602001516060015190565b136108225787516020015161080a90611220565b60208b01516060015161081d9190615692565b610841565b87515161082e90611220565b60208b0151606001516108419190615692565b8260a0018181516108529190615513565b90525060a082015160001361086d57600060a08301526108bb565b600061087d8d8b6000015161174e565b9050600061089961025f6108938e602001515190565b846117c7565b6108a29061565f565b9050808460a0015112156108b85760a084018190525b50505b60006040518061014001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c8152602001846040015181526020018460c00151151581526020018b604001516001600160a01b031681526020018b606001516001600160a01b031681526020016109358d602001515190565b81526000602082018190526040909101819052909150610954826117e0565b90506000846040015160000151826101e00151610971919061567b565b905061097c81611220565b60a08601518651606088015161099190611220565b61099b9190615513565b6109a59190615513565b6109af919061553b565b845288156109cf576109c58f8d60000151611a4f565b60208601526109e3565b6109dd8f8d60000151611a69565b60208601525b6109ff61025f6109f58f602001515190565b87602001516117c7565b60408501528915610b0e57610ac78f6001600160a01b031663bd02d0f5604051602001610a529060208082526012908201527113525397d0d3d31310551154905317d554d160721b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610a8691815260200190565b602060405180830381865afa158015610aa3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025f91906156c2565b6020850181905284511215610b0e57505060408051808201909152600e81526d1b5a5b8818dbdb1b185d195c985b60921b6020820152600196509450909250610bb2915050565b8351600012610b4457505060408051808201909152600381526203c20360ec1b6020820152600196509450909250610bb2915050565b604084015184511215610b9657505060408051808201909152601b81527a6d696e20636f6c6c61746572616c20666f72206c6576657261676560281b6020820152600196509450909250610bb2915050565b5050604080516020810190915260008082529650945090925050505b9750975097945050505050565b6020850151511580610bd657506020808601510151155b15610c0157602085810151805191015160405163bff65b3f60e01b81526103e4929190600401615562565b8351604051630ef68b4760e11b815273F62E9Cfa1ffD446E3516dC2F19f2818911Bf7d9691631ded168e91610c3a918b916004016156db565b60006040518083038186803b158015610c5257600080fd5b505af4158015610c66573d6000803e3d6000fd5b50505050610c7f84610c7a87516040015190565b611a83565b8115610d7d576000876001600160a01b031663bd02d0f5604051602001610ccf9060208082526015908201527413525397d413d4d2551253d397d4d2569157d554d1605a1b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610d0391815260200190565b602060405180830381865afa158015610d20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4491906156c2565b905080610d5387602001515190565b1015610d7b57602086015151816040516342f7d98d60e11b81526004016103e4929190615562565b505b6000806000610d928a8a8a8a8a8960006106f5565b9250925092508215610dcb5781816000015182602001518360400151604051631782422160e31b81526004016103e494939291906156f5565b50505050505050505050565b6000806000610de78689896116ad565b90506000610df88260000151611220565b610e058660200151611220565b610e0f9190615692565b9050600085604001511215610e30576040850151610e2d9082615513565b90505b6000811215610e4657600093509150610e989050565b6000610e588b8b88606001518a611ab3565b90506000610e6a8c8c60000151611a69565b905081811115610e78578091505b6000610e8b61025f8960000151856117c7565b8412159650929450505050505b965096945050505050565b6000806000610f1560405180610180016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610f30610f2688604001515190565b8951906000611aec565b9050610f4f81610f4589602090810151015190565b61025f919061567b565b8252604087015151610f7b578151610f6c61025f89602001515190565b610f76919061553b565b610f96565b610f8a61025f88602001515190565b8251610f96919061553b565b60208301819052604083018190526000121561111557604087015151610fc0578860600151610fc6565b88604001515b6001600160a01b031660608301819052610fe3908b908b90611b25565b6080830152604087015151610ffd57604088015151611004565b6020880151515b60a08301819052608083015161101a919061567b565b60c0830152875161103c908b908b906110358b604001515190565b6001611bcc565b60e083015288516040880151516110b2918c918560e001518660c00151604051602001611097906020808252601a90820152794d41585f504e4c5f464143544f525f464f525f5452414445525360301b604082015260600190565b60405160208183030381529060405280519060200120611c58565b610100830181905260e0830151148015906110d257506000826101000151135b80156110e2575060008260e00151135b156111155761110f6110f7836020015161142f565b83610100015161110a8560e0015161142f565b611ca8565b60208301525b8561112288602001515190565b0361113b5760208088015101515b610120830152611195565b6040870151511561116e576111308661115989602090810151015190565b611163919061567b565b60208901515161140c565b602087810151805191015161118490889061567b565b61118e91906154ff565b6101208301525b6111b782602001518361012001516111b28a602090810151015190565b611ce8565b61014083015260408201516101208301516020808a015101516111db929190611ce8565b610160830181905261014083015161012090930151929b909a50919850909650505050505050565b600081611211578251611217565b82602001515b90505b92915050565b60006001600160ff1b0382111561128a5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016103e4565b5090565b600080600061129c84611cf5565b90506000806112b8866000015187602001516000015185611d38565b91509150600082126112cf57909590945092505050565b6000806112e88860000151896020015160200151611e62565b91509150816112fe575091969095509350505050565b600061130a8983611f78565b90506000806113268b600001518c602001516000015185611d38565b9150915086821261133857868661133b565b81815b995099505050505050505050915091565b60008083121561135d575081611390565b600061136b86866001611ff2565b9050600061137c61025f85846117c7565b90508085131561138a578094505b84925050505b949350505050565b6000808312156113da576113ab82611220565b6113b483611220565b6113be908561553b565b6113c9906001615513565b6113d391906154d1565b905061121a565b6113e382611220565b60016113ee84611220565b6113f89086615513565b611402919061553b565b61121791906154d1565b600081600161141b8286615724565b6114259190615737565b61121791906154ff565b60008082121561128a5760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016103e4565b6000836000036114a457604051633df4253160e01b815260040160405180910390fd5b60006114b085876154ff565b90508280156114bf5750838111155b806114d35750821580156114d35750838110155b156114df579050611390565b808460405163e09ad0e960e01b81526004016103e4929190615562565b600061152260405180606001604052806000815260200160008152602001600081525090565b61152d898415611203565b808252602082015285158015906115445750600087115b15611648578261155c576115578561565f565b61155e565b845b60408201819052600013801561158857508561158682604001516115819061565f565b61142f565b115b156115ae578060400151866040516378320e4960e11b81526004016103e4929190615562565b60006115b987611220565b6115c88a84604001518b611ca8565b6115d291906154d1565b90506000816115e48460000151611220565b6115ee9190615513565b90506000811215611637578251604080850151905163cc32db9960e01b8152600481018490526024810192909252604482018c905260648201526084810189905260a4016103e4565b6116408161142f565b602084015250505b828015611659575083816020015110155b80611671575082158015611671575083816020015111155b15611681576020015190506116a2565b80602001518460405163e09ad0e960e01b81526004016103e4929190615562565b979650505050505050565b6116b561475f565b82604001516001600160a01b0316846001600160a01b0316036116dd57506020810151611747565b82606001516001600160a01b0316846001600160a01b03160361170557506040810151611747565b82602001516001600160a01b0316846001600160a01b03160361172a57508051611747565b8251604051635f2394d160e11b81526103e49186916004016156db565b9392505050565b6000826001600160a01b031663bd02d0f561176884612019565b6040518263ffffffff1660e01b815260040161178691815260200190565b602060405180830381865afa1580156117a3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121791906156c2565b6000611217838368327cb2734119d3b7a9601e1b6120bb565b6117e8614779565b6000611822836000015184602001518560600151866080015161180e8860400151515190565b604089015151602001518960e001516120c8565b9050600061183884600001518560400151612552565b905061184d84600001518560600151836125df565b6060830152610120840151156118835783516040850151516020015161187d91908660e0015187606001516126ee565b60a08301525b8160a00151606001518260a00151602001518360600151606001518460600151602001518561018001516118b79190615724565b6118c19190615737565b6118cb9190615724565b6118d59190615737565b61016083015260a082015160609081015181840151909101516118f89190615724565b826101400181815161190a9190615724565b9052508351604080860151805160208101519083015191909201515161193293929190612894565b604080840151606001919091528451908501515160200151611962919060a087015160408089015101515161290f565b604080840151608001919091528451908501515160200151611992919060c087015160408089015101515161290f565b826040015160a00181815250506119b18260400151856040015161292b565b60408301528351606085015160e08601516101008701516119d4939291906129a7565b82608001819052508161020001518260800151604001518360a0015160200151846060015160200151856101a00151611a0d9190615724565b611a179190615724565b611a219190615724565b611a2b9190615737565b6101c08301819052604083015151611a4291615724565b6101e08301525092915050565b6000826001600160a01b031663bd02d0f561176884612a0f565b6000826001600160a01b031663bd02d0f561176884612a60565b611a8d8282612a9b565b611aaf5781516040516341ce349f60e11b81526103e4919083906004016156db565b5050565b600080611ac1868685612ad4565b9050611acd8185612b27565b90506000611ae087876000015186612b57565b90506116a282826117c7565b60008215611b0d5781611b00578351611b06565b83602001515b9050611747565b81611b1c578360200151611390565b50509051919050565b600080611b3a84604001518560600151612bd1565b905080856001600160a01b031663bd02d0f5611b5a876000015187612c00565b6040518263ffffffff1660e01b8152600401611b7891815260200190565b602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906156c2565b611bc391906154ff565b95945050505050565b600080611bdd61025f888887612ad4565b90506000611bec888887612c88565b9050811580611bf9575080155b15611c0957600092505050611bc3565b6000611c16878787611aec565b90506000611c2761025f838561567b565b9050600087611c3f57611c3a828661553b565b611c49565b611c49858361553b565b9b9a5050505050505050505050565b600080841215611c69575082611c9e565b6000611c7788848989612ccf565b90506000611c8861025f86846117c7565b9050808613611c975785611c99565b805b925050505b9695505050505050565b600080611cbe85611cb886612ceb565b856120bb565b905060008413611cdf57611cd181611220565b611cda9061565f565b611bc3565b611bc381611220565b6000611390838584611ca8565b611cfd6148a6565b6000611d13836000015184602001516001612ad4565b90506000611d2b846000015185602001516000612ad4565b9050611390848383612cfc565b6000806000611d4f84600001518560200151612dee565b90506000611d6585604001518660600151612dee565b6060860151604087015160208801518851939450909211159111151460006001600160a01b03891663bd02d0f5611d9b8a612e10565b6040518263ffffffff1660e01b8152600401611db991815260200190565b602060405180830381865afa158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa91906156c2565b90508383108215611e30576000611e128b8b84612e53565b9050611e2086868386612e62565b8297509750505050505050611e5a565b600080611e3d8c8c612ea0565b91509150611e4e8787848488612fb4565b98509196505050505050505b935093915050565b6000806000846001600160a01b031663a6ed563e611e7f86612ffd565b6040518263ffffffff1660e01b8152600401611e9d91815260200190565b602060405180830381865afa158015611eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ede91906156c2565b905080611ef2576000809250925050611f71565b6001856001600160a01b031663dc97d962611f0c84613033565b6040518263ffffffff1660e01b8152600401611f2a91815260200190565b602060405180830381865afa158015611f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6b91906156c2565b92509250505b9250929050565b611f806148a6565b6000806000841315611f9c57611f958461142f565b9050611fab565b611fa86115818561565f565b91505b600085604001511215611fe7576000611fcb86604001516115819061565f565b9050611fd78184615724565b9250611fe38183615724565b9150505b611bc3858383612cfc565b6000806000612001868661309e565b91509150836120105780611c9e565b50949350505050565b6000604051602001612070906020808252602b908201527f4d41585f504f534954494f4e5f494d504143545f464143544f525f464f525f4c60408201526a49515549444154494f4e5360a81b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038416908201526060015b604051602081830303815290604052805190602001209050919050565b600061139084848461313a565b6120d0614779565b6120d8614779565b60c0810187905280516001600160a01b03861660409091015260006120fe8a8a88613224565b865160c081019290925260808201929092526001600160a01b039283166020820152929092529091508a1663bd02d0f5612138878a613563565b6040518263ffffffff1660e01b815260040161215691815260200190565b602060405180830381865afa158015612173573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219791906156c2565b60e083018190528851906121ac9086906117c7565b6121b691906154ff565b6101a08301526001600160a01b038a1663bd02d0f56121d4886135d6565b6040518263ffffffff1660e01b81526004016121f291815260200190565b602060405180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223391906156c2565b602083018051919091525151156122fa57896001600160a01b031663bd02d0f561226484602001516000015161360b565b6040518263ffffffff1660e01b815260040161228291815260200190565b602060405180830381865afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c391906156c2565b6020808401805182019290925290510151156122fa576122f0826101a001518360200151602001516117c7565b6020830151604001525b815151156123f057815160808082015160a090920191909152825160c08101519101516123279190615724565b825160600152815160c00151602080840151015111156123925781516060015160208084015101511161237157602080830151015182516060015161236c9190615737565b612373565b805b825160a0908101919091528251015181111561239257815160a0018190525b6123a9826101a00151836000015160a001516117c7565b825161012001526101a0820151825160c001516123c691906117c7565b825161010090810191909152825190810151610120909101516123e99190615724565b825160e001525b8151610100015160208301516040015111612411578151610100015161241b565b8160200151604001515b6102008301819052825161012001516101a084015161243a9190615737565b6124449190615737565b6101008301526040516001600160a01b038b169063bd02d0f59061249b906020016020808252601c908201527b2827a9a4aa24a7a72fa322a2afa922a1a2a4ab22a92fa320a1aa27a960211b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016124cf91815260200190565b602060405180830381865afa1580156124ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251091906156c2565b6101208301819052610100830151612527916117c7565b610140830181905261010083015161253f9190615737565b6101808301525098975050505050505050565b6000806125708461256585516020015190565b604086015151613644565b90508061258284602001516080015190565b11156125ad5760208301516080015181604051634cd96ac160e11b81526004016103e4929190615562565b60006125be84602001516080015190565b6125c89083615737565b9050611bc36125d985602001515190565b826117c7565b6125e76148a6565b6125ef6148a6565b82815283516125fe90846154ff565b816020018181525050846001600160a01b031663bd02d0f5604051602001612657906020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161268b91815260200190565b602060405180830381865afa1580156126a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126cc91906156c2565b6040820181905260208201516126e1916117c7565b6060820152949350505050565b6126f66148a6565b6126fe6148a6565b6000866001600160a01b031663bd02d0f56127188861365f565b6040518263ffffffff1660e01b815260040161273691815260200190565b602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277791906156c2565b90508060000361278957509050611390565b61279385826117c7565b80835284516127a2919061140c565b826020018181525050866001600160a01b031663bd02d0f56040516020016127fb906020808252601f908201527f4c49515549444154494f4e5f4645455f52454345495645525f464143544f5200604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161282f91815260200190565b602060405180830381865afa15801561284c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287091906156c2565b604083018190526020830151612885916117c7565b60608301525095945050505050565b6000846001600160a01b031663bd02d0f56128b086868661369b565b6040518263ffffffff1660e01b81526004016128ce91815260200190565b602060405180830381865afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc391906156c2565b6000846001600160a01b031663bd02d0f56128b086868661373c565b6129336148ce565b612957836060015161294a846020015160a0015190565b6020850151516001613789565b8352608083015161297e90612971846020015160c0015190565b6020850151516000613789565b602084015260a083015161299b90612971846020015160e0015190565b60408401525090919050565b6129af614904565b6129b7614904565b6001600160a01b0383166129cc579050611390565b6001600160a01b03831681526129e286846137c0565b602082018190528551906129f79086906117c7565b612a0191906154ff565b604082015295945050505050565b60006040516020016120709060208082526025908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4c495155494460408201526420aa24a7a760d91b606082015260800190565b60006040516020016120709060208082526015908201527426a4a72fa1a7a62620aa22a920a62fa320a1aa27a960591b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614806112175750506060909101516001600160a01b0391821691161490565b600080612ae984604001518560600151612bd1565b90506000612b0286866000015187604001518786613906565b90506000612b1b87876000015188606001518887613906565b90506116a28183615724565b600080821315612b4457612b3a82612ceb565b6113d39084615724565b612b4d82612ceb565b6112179084615737565b6000836001600160a01b031663bd02d0f5612b72858561398c565b6040518263ffffffff1660e01b8152600401612b9091815260200190565b602060405180830381865afa158015612bad573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139091906156c2565b6000816001600160a01b0316836001600160a01b031614612bf3576001612bf6565b60025b60ff169392505050565b6000604051602001612c31906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b600080612c9d84604001518560600151612bd1565b90506000612cb6868660000151876040015187866139ea565b90506000612b1b878760000151886060015188876139ea565b6000846001600160a01b031663bd02d0f56128b0868686613a07565b60008082121561128a575060000390565b612d046148a6565b60608401518390839015612d705760008660400151128015612d35575084612d3387604001516115819061565f565b115b15612d5b5785604001518560405163756d7c9d60e11b81526004016103e4929190615562565b612d69858760400151612b27565b9150612dca565b60008660400151128015612d93575083612d9187604001516115819061565f565b115b15612db95785604001518460405163022bc34560e61b81526004016103e4929190615562565b612dc7848760400151612b27565b90505b60408051608081018252958652602086019490945292840152506060820152919050565b6000818311612e0657612e018383615737565b611217565b6112178284615737565b6000604051602001612070906020808252601f908201527f504f534954494f4e5f494d504143545f4558504f4e454e545f464143544f5200604082015260600190565b60008060006120018686612ea0565b600084841081612e86612e76888787613a7b565b612e81888888613a7b565b612dee565b90506000612e948284613a94565b98975050505050505050565b6000806000846001600160a01b031663bd02d0f5612ebf866001613ab7565b6040518263ffffffff1660e01b8152600401612edd91815260200190565b602060405180830381865afa158015612efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1e91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613ab7565b6040518263ffffffff1660e01b8152600401612f5a91815260200190565b602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906156c2565b905080821115612fa9578091505b909590945092505050565b600080612fc2878685613a7b565b90506000612fd1878686613a7b565b90506000612fdf8383612dee565b90506000612fef82848611613a94565b9a9950505050505050505050565b60006040516020016120709060208082526010908201526f1592549515505317d513d2d15397d25160821b604082015260600190565b6000604051602001613076906020808252601f908201527f5649525455414c5f494e56454e544f52595f464f525f504f534954494f4e5300604082015260600190565b604051602081830303815290604052805190602001208260405160200161209e929190615562565b6000806000846001600160a01b031663bd02d0f56130bd866001613af3565b6040518263ffffffff1660e01b81526004016130db91815260200190565b602060405180830381865afa1580156130f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061311c91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613af3565b60008080600019858709858702925082811083820303915050806000036131745783828161316a5761316a6154a5565b0492505050611747565b8084116131bb5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016103e4565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000808080806001600160a01b03871661324c57506000935083925082915081905080613558565b6040516310ae4b6b60e31b81526000906001600160a01b038916906385725b589061327b908a9060040161574a565b602060405180830381865afa158015613298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132bc91906156c2565b90506000808080841561350a576040516306459e2360e51b8152600481018690526001600160a01b038d169063c8b3c46090602401602060405180830381865afa15801561330e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613332919061575e565b935060008c6001600160a01b0316631582a018866040518263ffffffff1660e01b8152600401613362919061574a565b602060405180830381865afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a391906156c2565b60405163039af9eb60e01b8152600481018290529091506001600160a01b038e169063039af9eb906024016040805180830381865afa1580156133ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061340e919061577b565b90945092506001600160a01b038e1663bd02d0f561342b83613b33565b6040518263ffffffff1660e01b815260040161344991815260200190565b602060405180830381865afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a91906156c2565b915060008d6001600160a01b03166371a6a790876040518263ffffffff1660e01b81526004016134ba919061574a565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb91906156c2565b90508015613507578093505b50505b600061352b61271061351c858761567b565b61352691906154ff565b613b74565b9050600061353885613b74565b905060006135468383615737565b979c50959a5095985096509450505050505b939792965093509350565b600060405160200161359c906020808252601390820152722827a9a4aa24a7a72fa322a2afa320a1aa27a960691b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038516908201528215156060820152608001612c6a565b6000604051602001612070906020808252600f908201526e282927afaa2920a222a92faa24a2a960891b604082015260600190565b600060405160200161307690602080825260139082015272282927afa224a9a1a7aaa72a2fa320a1aa27a960691b604082015260600190565b6000836001600160a01b031663bd02d0f5612b728585613b99565b6000604051602001612070906020808252601690820152752624a8aaa4a220aa24a7a72fa322a2afa320a1aa27a960511b604082015260600190565b60006040516020016136dc906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016136dc9060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b6000806137968587615737565b9050611c9e84826137ba66038d7ea4c6800068327cb2734119d3b7a9601e1b61567b565b86613bda565b600080836001600160a01b031663bd02d0f56040516020016138079060208082526011908201527026a0ac2faaa4afa322a2afa320a1aa27a960791b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161383b91815260200190565b602060405180830381865afa158015613858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387c91906156c2565b90506000846001600160a01b031663bd02d0f561389886613c01565b6040518263ffffffff1660e01b81526004016138b691815260200190565b602060405180830381865afa1580156138d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f791906156c2565b90508181106113905781611bc3565b600081866001600160a01b031663bd02d0f5613923888888613c34565b6040518263ffffffff1660e01b815260040161394191815260200190565b602060405180830381865afa15801561395e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398291906156c2565b611c9e91906154ff565b600060405160200161359c9060208082526032908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4f50454e5f49604082015271272a22a922a9aa2fa6aaa62a24a82624a2a960711b606082015260800190565b600081866001600160a01b031663bd02d0f5613923888888613c67565b6000604051602001613a3b906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a00161371d565b600080613a888584613ca4565b9050611bc381856117c7565b60008115613aa5576113d383611220565b613aae83611220565b6113d39061565f565b600060405160200161359c906020808252601690820152752827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960511b604082015260600190565b600060405160200161359c906020808252601a908201527926a0ac2fa827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960311b604082015260600190565b6000604051602001613076906020808252601b908201527a26a4a72fa0a32324a624a0aa22afa922aba0a9222fa320a1aa27a960291b604082015260600190565b6000612710613b8f68327cb2734119d3b7a9601e1b8461567b565b61121a91906154ff565b600060405160200161359c906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b60008115613bf657613bef8585856001613d03565b9050611390565b611bc385858561313a565b6000604051602001612070906020808252600d908201526c2aa4afa322a2afa320a1aa27a960991b604082015260600190565b60006040516020016136dc906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b60006040516020016136dc906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b600068327cb2734119d3b7a9601e1b831015613cc25750600061121a565b68327cb2734119d3b7a9601e1b8203613cdc57508161121a565b6000613cf8613cea85613d54565b613cf385613d54565b613d65565b905061139081613da5565b600080613d1186868661313a565b90506001836002811115613d2757613d2761579f565b148015613d44575060008480613d3f57613d3f6154a5565b868809115b15611bc357611c9e600182615724565b600061121a64e8d4a51000836154ff565b600082600003613d8b578115613d7c5760006113d3565b50670de0b6b3a764000061121a565b611217613da0613d9a85613db6565b84613e6c565b613e78565b600061121a64e8d4a510008361567b565b6000670de0b6b3a7640000821015613de457604051633621413760e21b8152600481018390526024016103e4565b6000613df9670de0b6b3a76400008404613ebe565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff198101613e22575050919050565b6706f05b59d3b200005b8015613e6457670de0b6b3a7640000828002049150671bc16d674ec800008210613e5c579283019260019190911c905b60011c613e2c565b505050919050565b60006112178383613fa1565b6000680a688906bd8b0000008210613ea657604051634a4f26f160e01b8152600481018390526024016103e4565b670de0b6b3a7640000604083901b0461174781614067565b6000600160801b8210613ede57608091821c91613edb9082615724565b90505b600160401b8210613efc57604091821c91613ef99082615724565b90505b600160201b8210613f1a57602091821c91613f179082615724565b90505b620100008210613f3757601091821c91613f349082615724565b90505b6101008210613f5357600891821c91613f509082615724565b90505b60108210613f6e57600491821c91613f6b9082615724565b90505b60048210613f8957600291821c91613f869082615724565b90505b60028210613f9c5761121a600182615724565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110613fe55760405163698d9a0160e11b8152600481018290526024016103e4565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff82119050826000036140235780670de0b6b3a764000085040194505050505061121a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b8216156140875768016a09e667f3bcc9090260401c5b6001603e1b8216156140a2576801306fe0a31b7152df0260401c5b6001603d1b8216156140bd576801172b83c7d517adce0260401c5b6001603c1b8216156140d85768010b5586cf9890f62a0260401c5b6001603b1b8216156140f3576801059b0d31585743ae0260401c5b6001603a1b82161561410e57680102c9a3e778060ee70260401c5b600160391b8216156141295768010163da9fb33356d80260401c5b600160381b82161561414457680100b1afa5abcbed610260401c5b600160371b82161561415f5768010058c86da1c09ea20260401c5b600160361b82161561417a576801002c605e2e8cec500260401c5b600160351b82161561419557680100162f3904051fa10260401c5b600160341b8216156141b0576801000b175effdc76ba0260401c5b600160331b8216156141cb57680100058ba01fb9f96d0260401c5b600160321b8216156141e65768010002c5cc37da94920260401c5b600160311b821615614201576801000162e525ee05470260401c5b600160301b82161561421c5768010000b17255775c040260401c5b6001602f1b821615614237576801000058b91b5bc9ae0260401c5b6001602e1b82161561425257680100002c5c89d5ec6d0260401c5b6001602d1b82161561426d5768010000162e43f4f8310260401c5b6001602c1b82161561428857680100000b1721bcfc9a0260401c5b6001602b1b8216156142a35768010000058b90cf1e6e0260401c5b6001602a1b8216156142be576801000002c5c863b73f0260401c5b600160291b8216156142d957680100000162e430e5a20260401c5b600160281b8216156142f4576801000000b1721835510260401c5b600160271b82161561430f57680100000058b90c0b490260401c5b600160261b82161561432a5768010000002c5c8601cc0260401c5b600160251b821615614345576801000000162e42fff00260401c5b600160241b8216156143605768010000000b17217fbb0260401c5b600160231b82161561437b576801000000058b90bfce0260401c5b600160221b82161561439657680100000002c5c85fe30260401c5b600160211b8216156143b15768010000000162e42ff10260401c5b600160201b8216156143cc57680100000000b17217f80260401c5b63800000008216156143e75768010000000058b90bfc0260401c5b6340000000821615614402576801000000002c5c85fe0260401c5b632000000082161561441d57680100000000162e42ff0260401c5b6310000000821615614438576801000000000b17217f0260401c5b630800000082161561445357680100000000058b90c00260401c5b630400000082161561446e5768010000000002c5c8600260401c5b6302000000821615614489576801000000000162e4300260401c5b63010000008216156144a45768010000000000b172180260401c5b628000008216156144be576801000000000058b90c0260401c5b624000008216156144d857680100000000002c5c860260401c5b622000008216156144f25768010000000000162e430260401c5b6210000082161561450c57680100000000000b17210260401c5b620800008216156145265768010000000000058b910260401c5b62040000821615614540576801000000000002c5c80260401c5b6202000082161561455a57680100000000000162e40260401c5b620100008216156145735761b172600160401b010260401c5b61800082161561458b576158b9600160401b010260401c5b6140008216156145a357612c5d600160401b010260401c5b6120008216156145bb5761162e600160401b010260401c5b6110008216156145d357610b17600160401b010260401c5b6108008216156145eb5761058c600160401b010260401c5b610400821615614603576102c6600160401b010260401c5b61020082161561461b57610163600160401b010260401c5b6101008216156146325760b1600160401b010260401c5b6080821615614648576059600160401b010260401c5b604082161561465e57602c600160401b010260401c5b6020821615614674576016600160401b010260401c5b601082161561468a57600b600160401b010260401c5b60088216156146a0576006600160401b010260401c5b60048216156146b6576003600160401b010260401c5b60028216156146cc576001600160401b010260401c5b60018216156146e2576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60405180606001604052806000815260200160008152602001600081525090565b6040518060e00160405280600081526020016000815260200161473b61475f565b81526020016000815260200160008152602001600081526020016000151581525090565b604051806040016040528060008152602001600081525090565b6040518061022001604052806147f06040518061014001604052806000801916815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200161481960405180606001604052806000815260200160008152602001600081525090565b81526020016148266148ce565b81526020016148336148a6565b8152602001614840614904565b815260200161484d6148a6565b815260200161485a61475f565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b03811182821017156149665761496661492e565b60405290565b604051608081016001600160401b03811182821017156149665761496661492e565b60405161018081016001600160401b03811182821017156149665761496661492e565b60405161010081016001600160401b03811182821017156149665761496661492e565b604051606081016001600160401b03811182821017156149665761496661492e565b60405161014081016001600160401b03811182821017156149665761496661492e565b604051601f8201601f191681016001600160401b0381118282101715614a4157614a4161492e565b604052919050565b6001600160a01b0381168114614a5e57600080fd5b50565b8035613f9c81614a49565b600060e08284031215614a7e57600080fd5b614a86614944565b90508135614a9381614a49565b81526020820135614aa381614a49565b60208201526040820135614ab681614a49565b60408201526060820135614ac981614a49565b6060820152614ada60808301614a61565b6080820152614aeb60a08301614a61565b60a0820152614afc60c08301614a61565b60c082015292915050565b600060808284031215614b1957600080fd5b614b2161496c565b90508135614b2e81614a49565b81526020820135614b3e81614a49565b60208201526040820135614b5181614a49565b60408201526060820135614b6481614a49565b606082015292915050565b60006001600160401b03821115614b8857614b8861492e565b5060051b60200190565b600082601f830112614ba357600080fd5b8135614bb6614bb182614b6f565b614a19565b8082825260208201915060208360051b860101925085831115614bd857600080fd5b602085015b83811015614bfe578035614bf081614a49565b835260209283019201614bdd565b5095945050505050565b803560098110613f9c57600080fd5b803560038110613f9c57600080fd5b60006101808284031215614c3957600080fd5b614c4161498e565b9050614c4c82614c08565b8152614c5a60208301614c17565b602082015260408281013590820152606080830135908201526080808301359082015260a0808301359082015260c0808301359082015260e080830135908201526101008083013590820152610120808301359082015261014080830135908201526101609182013591810191909152919050565b80358015158114613f9c57600080fd5b600060808284031215614cf157600080fd5b614cf961496c565b9050614d0482614ccf565b8152614d1260208301614ccf565b6020820152614d2360408301614ccf565b6040820152614b6460608301614ccf565b600082601f830112614d4557600080fd5b8135614d53614bb182614b6f565b8082825260208201915060208360051b860101925085831115614d7557600080fd5b602085015b83811015614bfe578035835260209283019201614d7a565b60006102408284031215614da557600080fd5b614dad61496c565b905081356001600160401b03811115614dc557600080fd5b82016101008185031215614dd857600080fd5b614de06149b1565b614de982614a61565b8152614df760208301614a61565b6020820152614e0860408301614a61565b6040820152614e1960608301614a61565b6060820152614e2a60808301614a61565b6080820152614e3b60a08301614a61565b60a0820152614e4c60c08301614a61565b60c082015260e08201356001600160401b03811115614e6a57600080fd5b614e7686828501614b92565b60e083015250825250614e8c8360208401614c26565b6020820152614e9f836101a08401614cdf565b60408201526102208201356001600160401b03811115614ebe57600080fd5b614eca84828501614d34565b60608301525092915050565b600060208284031215614ee857600080fd5b604051602081016001600160401b0381118282101715614f0a57614f0a61492e565b604052905080614f1983614ccf565b905292915050565b60008183036101c0811215614f3557600080fd5b614f3d6149d4565b91506060811215614f4d57600080fd5b614f556149d4565b8335614f6081614a49565b81526020840135614f7081614a49565b60208201526040840135614f8381614a49565b60408201528252610140605f1982011215614f9d57600080fd5b50614fa66149f6565b606083810135825260808085013560208085019190915260a080870135604086015260c0808801359486019490945260e0808801359386019390935261010080880135918601919091526101208088013594860194909452610140870135928501929092526101608601359184019190915261018085013591830191909152820152615036836101a08401614ed6565b604082015292915050565b803560028110613f9c57600080fd5b60006103a0828403121561506357600080fd5b61506b614944565b90506150778383614a6c565b81526150868360e08401614b07565b60208201526101608201356001600160401b038111156150a557600080fd5b6150b184828501614d92565b60408301525061018082013560608201526150d0836101a08401614f21565b608082015261036082013560a0820152614afc6103808301615041565b6000604082840312156150ff57600080fd5b604080519081016001600160401b03811182821017156151215761512161492e565b604052823581526020928301359281019290925250919050565b600060c0828403121561514d57600080fd5b6151556149d4565b905061516183836150ed565b815261517083604084016150ed565b602082015261503683608084016150ed565b60008060e0838503121561519557600080fd5b82356001600160401b038111156151ab57600080fd5b6151b785828601615050565b9250506151c7846020850161513b565b90509250929050565b60008060008061018085870312156151e757600080fd5b84356151f281614a49565b9350602085013561520281614a49565b92506152118660408701614b07565b91506152208660c0870161513b565b905092959194509250565b6000806060838503121561523e57600080fd5b82356001600160401b0381111561525457600080fd5b61526085828601615050565b9250506151c784602085016150ed565b6000806000806000806000610380888a03121561528c57600080fd5b873561529781614a49565b965060208801356152a781614a49565b95506152b68960408a01614f21565b94506152c6896102008a01614b07565b93506152d6896102808a0161513b565b92506152e56103408901614ccf565b91506152f46103608901614ccf565b905092959891949750929550565b6000815180845260005b818110156153285760208185018101518683018201520161530c565b506000602082860101526020601f19601f83011685010191505092915050565b831515815260a06020820152600061536360a0830185615302565b9050825160408301526020830151606083015260408301516080830152949350505050565b6000806000806000808688036102208112156153a357600080fd5b87356153ae81614a49565b96506153bd8960208a01614b07565b95506153cc8960a08a0161513b565b94506101608801356153dd81614a49565b93506153ec6101808901614ccf565b9250608061019f198201121561540157600080fd5b5061540a61496c565b6101a088013581526101c088013560208201526101e088013560408201526102009097013560608801525093969295509093909291565b6000806000806000610340868803121561545a57600080fd5b853561546581614a49565b94506154748760208801614b07565b93506154838760a0880161513b565b9250615493876101608801614f21565b94979396509194610320013592915050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000826154e0576154e06154a5565b600160ff1b8214600019841416156154fa576154fa6154bb565b500590565b60008261550e5761550e6154a5565b500490565b8082018281126000831280158216821582161715615533576155336154bb565b505092915050565b818103600083128015838313168383128216171561555b5761555b6154bb565b5092915050565b918252602082015260400190565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b6155b882825180518252602090810151910152565b602081810151805160408501529081015160608401525060400151805160808301526020015160a090910152565b6001600160a01b03858116825284166020820152610180810161560c6040830185615570565b611bc360c08301846155a3565b6001600160a01b038681168252851660208201526101a0810161563f6040830186615570565b61564c60c08301856155a3565b8215156101808301529695505050505050565b6000600160ff1b8201615674576156746154bb565b5060000390565b808202811582820484141761121a5761121a6154bb565b80820260008212600160ff1b841416156156ae576156ae6154bb565b818105831482151761121a5761121a6154bb565b6000602082840312156156d457600080fd5b5051919050565b6001600160a01b0392831681529116602082015260400190565b6080815260006157086080830187615302565b6020830195909552506040810192909252606090910152919050565b8082018082111561121a5761121a6154bb565b8181038181111561121a5761121a6154bb565b6001600160a01b0391909116815260200190565b60006020828403121561577057600080fd5b815161174781614a49565b6000806040838503121561578e57600080fd5b505080516020909101519092909150565b634e487b7160e01b600052602160045260246000fdfea264697066735822122001816216d36b781677541d9d282941e09404e8c34533d4bcc6284f9e6e05ef6964736f6c634300081d0033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100775760003560e01c8063610e3cb91461007c5780637396d38c146100be57806381db61b8146100e0578063a6dcd97614610110578063d7e3321114610132578063dac6485714610145578063e22de7931461016f575b600080fd5b61008f61008a366004615182565b61019d565b6040805195865260208601949094529284019190915260608301521515608082015260a0015b60405180910390f35b8180156100ca57600080fd5b506100de6100d93660046151d0565b61045a565b005b6100f36100ee36600461522b565b6105ad565b6040805193845260208401929092521515908201526060016100b5565b61012361011e366004615270565b6106f5565b6040516100b593929190615348565b6100de610140366004615270565b610bbf565b610158610153366004615388565b610dd7565b6040805192151583526020830191909152016100b5565b61018261017d366004615441565b610ea3565b604080519384526020840192909252908201526060016100b5565b60008060008060006101b88760400151602001516040015190565b6000036101f05760008060006101df6101d78b60800151604001515190565b8a5190611203565b600094509450945094509450610450565b6102246040518060a00160405280600081526020016000815260200160008152602001600015158152602001600081525090565b604080516080810182528951516001600160a01b031681526020808b0151818301528a83015101518201516102829282019061026490611220565b611220565b81526020016102798b60400151604001515190565b1515905261128e565b1515606083015280825288515160208a01515160408b01516102b393906102ae90602001516040015190565b61134c565b808252600012156102e3578651602001516102cd90611220565b81516102d991906154d1565b60208201526102f8565b80518751516102f29190611398565b60208201525b608088015160400151511561033557865160200151604089015161032190602001516040015190565b61032b91906154ff565b6040820152610359565b61035361034b8960400151602001516040015190565b88515161140c565b60408201525b600061036b8960800151604001515190565b156103935781602001516103828360400151611220565b61038c9190615513565b90506103b2565b81602001516103a58360400151611220565b6103af919061553b565b90505b60008112156103ed57815160408a8101516020015101516040516378320e4960e11b81526004016103e4929190615562565b60405180910390fd5b6104286104038a60400151602001516040015190565b61040c8361142f565b60408c01516020015160a0015160808d01516040015151611481565b6080830181905282516020840151604085015160609095015191995097509295509350909150505b9295509295909350565b60405163034aadf760e61b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__9063d2ab7dc0906104979087908790879087906004016155e6565b60006040518083038186803b1580156104af57600080fd5b505af41580156104c3573d6000803e3d6000fd5b5050604051631450a87960e01b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__9250631450a8799150610507908790879087908790600190600401615619565b60006040518083038186803b15801561051f57600080fd5b505af4158015610533573d6000803e3d6000fd5b5050604051631450a87960e01b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__9250631450a8799150610577908790879087908790600090600401615619565b60006040518083038186803b15801561058f57600080fd5b505af41580156105a3573d6000803e3d6000fd5b5050505050505050565b6000806000806105c68660400151602001516040015190565b9050806000036105fb5760006105ed6105e58860800151604001515190565b879015611203565b6000935093509350506106ee565b610621604051806060016040528060008152602001600015158152602001600081525090565b604080516080810182528851516001600160a01b031681526020808a01519082015261067091810161065285611220565b61065b9061565f565b81526020016102798a60400151604001515190565b1515602080840191909152818352885151908901515160408a015161069f93906102ae90602001516040015190565b80825260808801516020808201518051908201516040808d01519093015160a001519290930151516106d6948b94929388926114fc565b60408201819052815160209092015191955093509150505b9250925092565b600060606107016146f9565b61070961471a565b6107116146f9565b6107248c8a8a8d61017d8f602001515190565b5050825261073e6107378b516040015190565b8a8a6116ad565b60408301819052516107558b602001516040015190565b61075f919061567b565b606083015261077361025f8b602001515190565b61077c9061565f565b8260800181815250506107be60405180608001604052808e6001600160a01b031681526020018b8152602001846080015181526020016102798d604001515190565b151560c084015260a08301819052895160208c0151516107e0928f929161134c565b60a083015260006107f68b602001516060015190565b136108225787516020015161080a90611220565b60208b01516060015161081d9190615692565b610841565b87515161082e90611220565b60208b0151606001516108419190615692565b8260a0018181516108529190615513565b90525060a082015160001361086d57600060a08301526108bb565b600061087d8d8b6000015161174e565b9050600061089961025f6108938e602001515190565b846117c7565b6108a29061565f565b9050808460a0015112156108b85760a084018190525b50505b60006040518061014001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c8152602001846040015181526020018460c00151151581526020018b604001516001600160a01b031681526020018b606001516001600160a01b031681526020016109358d602001515190565b81526000602082018190526040909101819052909150610954826117e0565b90506000846040015160000151826101e00151610971919061567b565b905061097c81611220565b60a08601518651606088015161099190611220565b61099b9190615513565b6109a59190615513565b6109af919061553b565b845288156109cf576109c58f8d60000151611a4f565b60208601526109e3565b6109dd8f8d60000151611a69565b60208601525b6109ff61025f6109f58f602001515190565b87602001516117c7565b60408501528915610b0e57610ac78f6001600160a01b031663bd02d0f5604051602001610a529060208082526012908201527113525397d0d3d31310551154905317d554d160721b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610a8691815260200190565b602060405180830381865afa158015610aa3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025f91906156c2565b6020850181905284511215610b0e57505060408051808201909152600e81526d1b5a5b8818dbdb1b185d195c985b60921b6020820152600196509450909250610bb2915050565b8351600012610b4457505060408051808201909152600381526203c20360ec1b6020820152600196509450909250610bb2915050565b604084015184511215610b9657505060408051808201909152601b81527a6d696e20636f6c6c61746572616c20666f72206c6576657261676560281b6020820152600196509450909250610bb2915050565b5050604080516020810190915260008082529650945090925050505b9750975097945050505050565b6020850151511580610bd657506020808601510151155b15610c0157602085810151805191015160405163bff65b3f60e01b81526103e4929190600401615562565b8351604051630ef68b4760e11b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__91631ded168e91610c3a918b916004016156db565b60006040518083038186803b158015610c5257600080fd5b505af4158015610c66573d6000803e3d6000fd5b50505050610c7f84610c7a87516040015190565b611a83565b8115610d7d576000876001600160a01b031663bd02d0f5604051602001610ccf9060208082526015908201527413525397d413d4d2551253d397d4d2569157d554d1605a1b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610d0391815260200190565b602060405180830381865afa158015610d20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4491906156c2565b905080610d5387602001515190565b1015610d7b57602086015151816040516342f7d98d60e11b81526004016103e4929190615562565b505b6000806000610d928a8a8a8a8a8960006106f5565b9250925092508215610dcb5781816000015182602001518360400151604051631782422160e31b81526004016103e494939291906156f5565b50505050505050505050565b6000806000610de78689896116ad565b90506000610df88260000151611220565b610e058660200151611220565b610e0f9190615692565b9050600085604001511215610e30576040850151610e2d9082615513565b90505b6000811215610e4657600093509150610e989050565b6000610e588b8b88606001518a611ab3565b90506000610e6a8c8c60000151611a69565b905081811115610e78578091505b6000610e8b61025f8960000151856117c7565b8412159650929450505050505b965096945050505050565b6000806000610f1560405180610180016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610f30610f2688604001515190565b8951906000611aec565b9050610f4f81610f4589602090810151015190565b61025f919061567b565b8252604087015151610f7b578151610f6c61025f89602001515190565b610f76919061553b565b610f96565b610f8a61025f88602001515190565b8251610f96919061553b565b60208301819052604083018190526000121561111557604087015151610fc0578860600151610fc6565b88604001515b6001600160a01b031660608301819052610fe3908b908b90611b25565b6080830152604087015151610ffd57604088015151611004565b6020880151515b60a08301819052608083015161101a919061567b565b60c0830152875161103c908b908b906110358b604001515190565b6001611bcc565b60e083015288516040880151516110b2918c918560e001518660c00151604051602001611097906020808252601a90820152794d41585f504e4c5f464143544f525f464f525f5452414445525360301b604082015260600190565b60405160208183030381529060405280519060200120611c58565b610100830181905260e0830151148015906110d257506000826101000151135b80156110e2575060008260e00151135b156111155761110f6110f7836020015161142f565b83610100015161110a8560e0015161142f565b611ca8565b60208301525b8561112288602001515190565b0361113b5760208088015101515b610120830152611195565b6040870151511561116e576111308661115989602090810151015190565b611163919061567b565b60208901515161140c565b602087810151805191015161118490889061567b565b61118e91906154ff565b6101208301525b6111b782602001518361012001516111b28a602090810151015190565b611ce8565b61014083015260408201516101208301516020808a015101516111db929190611ce8565b610160830181905261014083015161012090930151929b909a50919850909650505050505050565b600081611211578251611217565b82602001515b90505b92915050565b60006001600160ff1b0382111561128a5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016103e4565b5090565b600080600061129c84611cf5565b90506000806112b8866000015187602001516000015185611d38565b91509150600082126112cf57909590945092505050565b6000806112e88860000151896020015160200151611e62565b91509150816112fe575091969095509350505050565b600061130a8983611f78565b90506000806113268b600001518c602001516000015185611d38565b9150915086821261133857868661133b565b81815b995099505050505050505050915091565b60008083121561135d575081611390565b600061136b86866001611ff2565b9050600061137c61025f85846117c7565b90508085131561138a578094505b84925050505b949350505050565b6000808312156113da576113ab82611220565b6113b483611220565b6113be908561553b565b6113c9906001615513565b6113d391906154d1565b905061121a565b6113e382611220565b60016113ee84611220565b6113f89086615513565b611402919061553b565b61121791906154d1565b600081600161141b8286615724565b6114259190615737565b61121791906154ff565b60008082121561128a5760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016103e4565b6000836000036114a457604051633df4253160e01b815260040160405180910390fd5b60006114b085876154ff565b90508280156114bf5750838111155b806114d35750821580156114d35750838110155b156114df579050611390565b808460405163e09ad0e960e01b81526004016103e4929190615562565b600061152260405180606001604052806000815260200160008152602001600081525090565b61152d898415611203565b808252602082015285158015906115445750600087115b15611648578261155c576115578561565f565b61155e565b845b60408201819052600013801561158857508561158682604001516115819061565f565b61142f565b115b156115ae578060400151866040516378320e4960e11b81526004016103e4929190615562565b60006115b987611220565b6115c88a84604001518b611ca8565b6115d291906154d1565b90506000816115e48460000151611220565b6115ee9190615513565b90506000811215611637578251604080850151905163cc32db9960e01b8152600481018490526024810192909252604482018c905260648201526084810189905260a4016103e4565b6116408161142f565b602084015250505b828015611659575083816020015110155b80611671575082158015611671575083816020015111155b15611681576020015190506116a2565b80602001518460405163e09ad0e960e01b81526004016103e4929190615562565b979650505050505050565b6116b561475f565b82604001516001600160a01b0316846001600160a01b0316036116dd57506020810151611747565b82606001516001600160a01b0316846001600160a01b03160361170557506040810151611747565b82602001516001600160a01b0316846001600160a01b03160361172a57508051611747565b8251604051635f2394d160e11b81526103e49186916004016156db565b9392505050565b6000826001600160a01b031663bd02d0f561176884612019565b6040518263ffffffff1660e01b815260040161178691815260200190565b602060405180830381865afa1580156117a3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121791906156c2565b6000611217838368327cb2734119d3b7a9601e1b6120bb565b6117e8614779565b6000611822836000015184602001518560600151866080015161180e8860400151515190565b604089015151602001518960e001516120c8565b9050600061183884600001518560400151612552565b905061184d84600001518560600151836125df565b6060830152610120840151156118835783516040850151516020015161187d91908660e0015187606001516126ee565b60a08301525b8160a00151606001518260a00151602001518360600151606001518460600151602001518561018001516118b79190615724565b6118c19190615737565b6118cb9190615724565b6118d59190615737565b61016083015260a082015160609081015181840151909101516118f89190615724565b826101400181815161190a9190615724565b9052508351604080860151805160208101519083015191909201515161193293929190612894565b604080840151606001919091528451908501515160200151611962919060a087015160408089015101515161290f565b604080840151608001919091528451908501515160200151611992919060c087015160408089015101515161290f565b826040015160a00181815250506119b18260400151856040015161292b565b60408301528351606085015160e08601516101008701516119d4939291906129a7565b82608001819052508161020001518260800151604001518360a0015160200151846060015160200151856101a00151611a0d9190615724565b611a179190615724565b611a219190615724565b611a2b9190615737565b6101c08301819052604083015151611a4291615724565b6101e08301525092915050565b6000826001600160a01b031663bd02d0f561176884612a0f565b6000826001600160a01b031663bd02d0f561176884612a60565b611a8d8282612a9b565b611aaf5781516040516341ce349f60e11b81526103e4919083906004016156db565b5050565b600080611ac1868685612ad4565b9050611acd8185612b27565b90506000611ae087876000015186612b57565b90506116a282826117c7565b60008215611b0d5781611b00578351611b06565b83602001515b9050611747565b81611b1c578360200151611390565b50509051919050565b600080611b3a84604001518560600151612bd1565b905080856001600160a01b031663bd02d0f5611b5a876000015187612c00565b6040518263ffffffff1660e01b8152600401611b7891815260200190565b602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906156c2565b611bc391906154ff565b95945050505050565b600080611bdd61025f888887612ad4565b90506000611bec888887612c88565b9050811580611bf9575080155b15611c0957600092505050611bc3565b6000611c16878787611aec565b90506000611c2761025f838561567b565b9050600087611c3f57611c3a828661553b565b611c49565b611c49858361553b565b9b9a5050505050505050505050565b600080841215611c69575082611c9e565b6000611c7788848989612ccf565b90506000611c8861025f86846117c7565b9050808613611c975785611c99565b805b925050505b9695505050505050565b600080611cbe85611cb886612ceb565b856120bb565b905060008413611cdf57611cd181611220565b611cda9061565f565b611bc3565b611bc381611220565b6000611390838584611ca8565b611cfd6148a6565b6000611d13836000015184602001516001612ad4565b90506000611d2b846000015185602001516000612ad4565b9050611390848383612cfc565b6000806000611d4f84600001518560200151612dee565b90506000611d6585604001518660600151612dee565b6060860151604087015160208801518851939450909211159111151460006001600160a01b03891663bd02d0f5611d9b8a612e10565b6040518263ffffffff1660e01b8152600401611db991815260200190565b602060405180830381865afa158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa91906156c2565b90508383108215611e30576000611e128b8b84612e53565b9050611e2086868386612e62565b8297509750505050505050611e5a565b600080611e3d8c8c612ea0565b91509150611e4e8787848488612fb4565b98509196505050505050505b935093915050565b6000806000846001600160a01b031663a6ed563e611e7f86612ffd565b6040518263ffffffff1660e01b8152600401611e9d91815260200190565b602060405180830381865afa158015611eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ede91906156c2565b905080611ef2576000809250925050611f71565b6001856001600160a01b031663dc97d962611f0c84613033565b6040518263ffffffff1660e01b8152600401611f2a91815260200190565b602060405180830381865afa158015611f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6b91906156c2565b92509250505b9250929050565b611f806148a6565b6000806000841315611f9c57611f958461142f565b9050611fab565b611fa86115818561565f565b91505b600085604001511215611fe7576000611fcb86604001516115819061565f565b9050611fd78184615724565b9250611fe38183615724565b9150505b611bc3858383612cfc565b6000806000612001868661309e565b91509150836120105780611c9e565b50949350505050565b6000604051602001612070906020808252602b908201527f4d41585f504f534954494f4e5f494d504143545f464143544f525f464f525f4c60408201526a49515549444154494f4e5360a81b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038416908201526060015b604051602081830303815290604052805190602001209050919050565b600061139084848461313a565b6120d0614779565b6120d8614779565b60c0810187905280516001600160a01b03861660409091015260006120fe8a8a88613224565b865160c081019290925260808201929092526001600160a01b039283166020820152929092529091508a1663bd02d0f5612138878a613563565b6040518263ffffffff1660e01b815260040161215691815260200190565b602060405180830381865afa158015612173573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219791906156c2565b60e083018190528851906121ac9086906117c7565b6121b691906154ff565b6101a08301526001600160a01b038a1663bd02d0f56121d4886135d6565b6040518263ffffffff1660e01b81526004016121f291815260200190565b602060405180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223391906156c2565b602083018051919091525151156122fa57896001600160a01b031663bd02d0f561226484602001516000015161360b565b6040518263ffffffff1660e01b815260040161228291815260200190565b602060405180830381865afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c391906156c2565b6020808401805182019290925290510151156122fa576122f0826101a001518360200151602001516117c7565b6020830151604001525b815151156123f057815160808082015160a090920191909152825160c08101519101516123279190615724565b825160600152815160c00151602080840151015111156123925781516060015160208084015101511161237157602080830151015182516060015161236c9190615737565b612373565b805b825160a0908101919091528251015181111561239257815160a0018190525b6123a9826101a00151836000015160a001516117c7565b825161012001526101a0820151825160c001516123c691906117c7565b825161010090810191909152825190810151610120909101516123e99190615724565b825160e001525b8151610100015160208301516040015111612411578151610100015161241b565b8160200151604001515b6102008301819052825161012001516101a084015161243a9190615737565b6124449190615737565b6101008301526040516001600160a01b038b169063bd02d0f59061249b906020016020808252601c908201527b2827a9a4aa24a7a72fa322a2afa922a1a2a4ab22a92fa320a1aa27a960211b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016124cf91815260200190565b602060405180830381865afa1580156124ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251091906156c2565b6101208301819052610100830151612527916117c7565b610140830181905261010083015161253f9190615737565b6101808301525098975050505050505050565b6000806125708461256585516020015190565b604086015151613644565b90508061258284602001516080015190565b11156125ad5760208301516080015181604051634cd96ac160e11b81526004016103e4929190615562565b60006125be84602001516080015190565b6125c89083615737565b9050611bc36125d985602001515190565b826117c7565b6125e76148a6565b6125ef6148a6565b82815283516125fe90846154ff565b816020018181525050846001600160a01b031663bd02d0f5604051602001612657906020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161268b91815260200190565b602060405180830381865afa1580156126a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126cc91906156c2565b6040820181905260208201516126e1916117c7565b6060820152949350505050565b6126f66148a6565b6126fe6148a6565b6000866001600160a01b031663bd02d0f56127188861365f565b6040518263ffffffff1660e01b815260040161273691815260200190565b602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277791906156c2565b90508060000361278957509050611390565b61279385826117c7565b80835284516127a2919061140c565b826020018181525050866001600160a01b031663bd02d0f56040516020016127fb906020808252601f908201527f4c49515549444154494f4e5f4645455f52454345495645525f464143544f5200604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161282f91815260200190565b602060405180830381865afa15801561284c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287091906156c2565b604083018190526020830151612885916117c7565b60608301525095945050505050565b6000846001600160a01b031663bd02d0f56128b086868661369b565b6040518263ffffffff1660e01b81526004016128ce91815260200190565b602060405180830381865afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc391906156c2565b6000846001600160a01b031663bd02d0f56128b086868661373c565b6129336148ce565b612957836060015161294a846020015160a0015190565b6020850151516001613789565b8352608083015161297e90612971846020015160c0015190565b6020850151516000613789565b602084015260a083015161299b90612971846020015160e0015190565b60408401525090919050565b6129af614904565b6129b7614904565b6001600160a01b0383166129cc579050611390565b6001600160a01b03831681526129e286846137c0565b602082018190528551906129f79086906117c7565b612a0191906154ff565b604082015295945050505050565b60006040516020016120709060208082526025908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4c495155494460408201526420aa24a7a760d91b606082015260800190565b60006040516020016120709060208082526015908201527426a4a72fa1a7a62620aa22a920a62fa320a1aa27a960591b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614806112175750506060909101516001600160a01b0391821691161490565b600080612ae984604001518560600151612bd1565b90506000612b0286866000015187604001518786613906565b90506000612b1b87876000015188606001518887613906565b90506116a28183615724565b600080821315612b4457612b3a82612ceb565b6113d39084615724565b612b4d82612ceb565b6112179084615737565b6000836001600160a01b031663bd02d0f5612b72858561398c565b6040518263ffffffff1660e01b8152600401612b9091815260200190565b602060405180830381865afa158015612bad573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139091906156c2565b6000816001600160a01b0316836001600160a01b031614612bf3576001612bf6565b60025b60ff169392505050565b6000604051602001612c31906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b600080612c9d84604001518560600151612bd1565b90506000612cb6868660000151876040015187866139ea565b90506000612b1b878760000151886060015188876139ea565b6000846001600160a01b031663bd02d0f56128b0868686613a07565b60008082121561128a575060000390565b612d046148a6565b60608401518390839015612d705760008660400151128015612d35575084612d3387604001516115819061565f565b115b15612d5b5785604001518560405163756d7c9d60e11b81526004016103e4929190615562565b612d69858760400151612b27565b9150612dca565b60008660400151128015612d93575083612d9187604001516115819061565f565b115b15612db95785604001518460405163022bc34560e61b81526004016103e4929190615562565b612dc7848760400151612b27565b90505b60408051608081018252958652602086019490945292840152506060820152919050565b6000818311612e0657612e018383615737565b611217565b6112178284615737565b6000604051602001612070906020808252601f908201527f504f534954494f4e5f494d504143545f4558504f4e454e545f464143544f5200604082015260600190565b60008060006120018686612ea0565b600084841081612e86612e76888787613a7b565b612e81888888613a7b565b612dee565b90506000612e948284613a94565b98975050505050505050565b6000806000846001600160a01b031663bd02d0f5612ebf866001613ab7565b6040518263ffffffff1660e01b8152600401612edd91815260200190565b602060405180830381865afa158015612efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1e91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613ab7565b6040518263ffffffff1660e01b8152600401612f5a91815260200190565b602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906156c2565b905080821115612fa9578091505b909590945092505050565b600080612fc2878685613a7b565b90506000612fd1878686613a7b565b90506000612fdf8383612dee565b90506000612fef82848611613a94565b9a9950505050505050505050565b60006040516020016120709060208082526010908201526f1592549515505317d513d2d15397d25160821b604082015260600190565b6000604051602001613076906020808252601f908201527f5649525455414c5f494e56454e544f52595f464f525f504f534954494f4e5300604082015260600190565b604051602081830303815290604052805190602001208260405160200161209e929190615562565b6000806000846001600160a01b031663bd02d0f56130bd866001613af3565b6040518263ffffffff1660e01b81526004016130db91815260200190565b602060405180830381865afa1580156130f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061311c91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613af3565b60008080600019858709858702925082811083820303915050806000036131745783828161316a5761316a6154a5565b0492505050611747565b8084116131bb5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016103e4565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000808080806001600160a01b03871661324c57506000935083925082915081905080613558565b6040516310ae4b6b60e31b81526000906001600160a01b038916906385725b589061327b908a9060040161574a565b602060405180830381865afa158015613298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132bc91906156c2565b90506000808080841561350a576040516306459e2360e51b8152600481018690526001600160a01b038d169063c8b3c46090602401602060405180830381865afa15801561330e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613332919061575e565b935060008c6001600160a01b0316631582a018866040518263ffffffff1660e01b8152600401613362919061574a565b602060405180830381865afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a391906156c2565b60405163039af9eb60e01b8152600481018290529091506001600160a01b038e169063039af9eb906024016040805180830381865afa1580156133ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061340e919061577b565b90945092506001600160a01b038e1663bd02d0f561342b83613b33565b6040518263ffffffff1660e01b815260040161344991815260200190565b602060405180830381865afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a91906156c2565b915060008d6001600160a01b03166371a6a790876040518263ffffffff1660e01b81526004016134ba919061574a565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb91906156c2565b90508015613507578093505b50505b600061352b61271061351c858761567b565b61352691906154ff565b613b74565b9050600061353885613b74565b905060006135468383615737565b979c50959a5095985096509450505050505b939792965093509350565b600060405160200161359c906020808252601390820152722827a9a4aa24a7a72fa322a2afa320a1aa27a960691b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038516908201528215156060820152608001612c6a565b6000604051602001612070906020808252600f908201526e282927afaa2920a222a92faa24a2a960891b604082015260600190565b600060405160200161307690602080825260139082015272282927afa224a9a1a7aaa72a2fa320a1aa27a960691b604082015260600190565b6000836001600160a01b031663bd02d0f5612b728585613b99565b6000604051602001612070906020808252601690820152752624a8aaa4a220aa24a7a72fa322a2afa320a1aa27a960511b604082015260600190565b60006040516020016136dc906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016136dc9060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b6000806137968587615737565b9050611c9e84826137ba66038d7ea4c6800068327cb2734119d3b7a9601e1b61567b565b86613bda565b600080836001600160a01b031663bd02d0f56040516020016138079060208082526011908201527026a0ac2faaa4afa322a2afa320a1aa27a960791b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161383b91815260200190565b602060405180830381865afa158015613858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387c91906156c2565b90506000846001600160a01b031663bd02d0f561389886613c01565b6040518263ffffffff1660e01b81526004016138b691815260200190565b602060405180830381865afa1580156138d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f791906156c2565b90508181106113905781611bc3565b600081866001600160a01b031663bd02d0f5613923888888613c34565b6040518263ffffffff1660e01b815260040161394191815260200190565b602060405180830381865afa15801561395e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398291906156c2565b611c9e91906154ff565b600060405160200161359c9060208082526032908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4f50454e5f49604082015271272a22a922a9aa2fa6aaa62a24a82624a2a960711b606082015260800190565b600081866001600160a01b031663bd02d0f5613923888888613c67565b6000604051602001613a3b906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a00161371d565b600080613a888584613ca4565b9050611bc381856117c7565b60008115613aa5576113d383611220565b613aae83611220565b6113d39061565f565b600060405160200161359c906020808252601690820152752827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960511b604082015260600190565b600060405160200161359c906020808252601a908201527926a0ac2fa827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960311b604082015260600190565b6000604051602001613076906020808252601b908201527a26a4a72fa0a32324a624a0aa22afa922aba0a9222fa320a1aa27a960291b604082015260600190565b6000612710613b8f68327cb2734119d3b7a9601e1b8461567b565b61121a91906154ff565b600060405160200161359c906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b60008115613bf657613bef8585856001613d03565b9050611390565b611bc385858561313a565b6000604051602001612070906020808252600d908201526c2aa4afa322a2afa320a1aa27a960991b604082015260600190565b60006040516020016136dc906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b60006040516020016136dc906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b600068327cb2734119d3b7a9601e1b831015613cc25750600061121a565b68327cb2734119d3b7a9601e1b8203613cdc57508161121a565b6000613cf8613cea85613d54565b613cf385613d54565b613d65565b905061139081613da5565b600080613d1186868661313a565b90506001836002811115613d2757613d2761579f565b148015613d44575060008480613d3f57613d3f6154a5565b868809115b15611bc357611c9e600182615724565b600061121a64e8d4a51000836154ff565b600082600003613d8b578115613d7c5760006113d3565b50670de0b6b3a764000061121a565b611217613da0613d9a85613db6565b84613e6c565b613e78565b600061121a64e8d4a510008361567b565b6000670de0b6b3a7640000821015613de457604051633621413760e21b8152600481018390526024016103e4565b6000613df9670de0b6b3a76400008404613ebe565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff198101613e22575050919050565b6706f05b59d3b200005b8015613e6457670de0b6b3a7640000828002049150671bc16d674ec800008210613e5c579283019260019190911c905b60011c613e2c565b505050919050565b60006112178383613fa1565b6000680a688906bd8b0000008210613ea657604051634a4f26f160e01b8152600481018390526024016103e4565b670de0b6b3a7640000604083901b0461174781614067565b6000600160801b8210613ede57608091821c91613edb9082615724565b90505b600160401b8210613efc57604091821c91613ef99082615724565b90505b600160201b8210613f1a57602091821c91613f179082615724565b90505b620100008210613f3757601091821c91613f349082615724565b90505b6101008210613f5357600891821c91613f509082615724565b90505b60108210613f6e57600491821c91613f6b9082615724565b90505b60048210613f8957600291821c91613f869082615724565b90505b60028210613f9c5761121a600182615724565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110613fe55760405163698d9a0160e11b8152600481018290526024016103e4565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff82119050826000036140235780670de0b6b3a764000085040194505050505061121a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b8216156140875768016a09e667f3bcc9090260401c5b6001603e1b8216156140a2576801306fe0a31b7152df0260401c5b6001603d1b8216156140bd576801172b83c7d517adce0260401c5b6001603c1b8216156140d85768010b5586cf9890f62a0260401c5b6001603b1b8216156140f3576801059b0d31585743ae0260401c5b6001603a1b82161561410e57680102c9a3e778060ee70260401c5b600160391b8216156141295768010163da9fb33356d80260401c5b600160381b82161561414457680100b1afa5abcbed610260401c5b600160371b82161561415f5768010058c86da1c09ea20260401c5b600160361b82161561417a576801002c605e2e8cec500260401c5b600160351b82161561419557680100162f3904051fa10260401c5b600160341b8216156141b0576801000b175effdc76ba0260401c5b600160331b8216156141cb57680100058ba01fb9f96d0260401c5b600160321b8216156141e65768010002c5cc37da94920260401c5b600160311b821615614201576801000162e525ee05470260401c5b600160301b82161561421c5768010000b17255775c040260401c5b6001602f1b821615614237576801000058b91b5bc9ae0260401c5b6001602e1b82161561425257680100002c5c89d5ec6d0260401c5b6001602d1b82161561426d5768010000162e43f4f8310260401c5b6001602c1b82161561428857680100000b1721bcfc9a0260401c5b6001602b1b8216156142a35768010000058b90cf1e6e0260401c5b6001602a1b8216156142be576801000002c5c863b73f0260401c5b600160291b8216156142d957680100000162e430e5a20260401c5b600160281b8216156142f4576801000000b1721835510260401c5b600160271b82161561430f57680100000058b90c0b490260401c5b600160261b82161561432a5768010000002c5c8601cc0260401c5b600160251b821615614345576801000000162e42fff00260401c5b600160241b8216156143605768010000000b17217fbb0260401c5b600160231b82161561437b576801000000058b90bfce0260401c5b600160221b82161561439657680100000002c5c85fe30260401c5b600160211b8216156143b15768010000000162e42ff10260401c5b600160201b8216156143cc57680100000000b17217f80260401c5b63800000008216156143e75768010000000058b90bfc0260401c5b6340000000821615614402576801000000002c5c85fe0260401c5b632000000082161561441d57680100000000162e42ff0260401c5b6310000000821615614438576801000000000b17217f0260401c5b630800000082161561445357680100000000058b90c00260401c5b630400000082161561446e5768010000000002c5c8600260401c5b6302000000821615614489576801000000000162e4300260401c5b63010000008216156144a45768010000000000b172180260401c5b628000008216156144be576801000000000058b90c0260401c5b624000008216156144d857680100000000002c5c860260401c5b622000008216156144f25768010000000000162e430260401c5b6210000082161561450c57680100000000000b17210260401c5b620800008216156145265768010000000000058b910260401c5b62040000821615614540576801000000000002c5c80260401c5b6202000082161561455a57680100000000000162e40260401c5b620100008216156145735761b172600160401b010260401c5b61800082161561458b576158b9600160401b010260401c5b6140008216156145a357612c5d600160401b010260401c5b6120008216156145bb5761162e600160401b010260401c5b6110008216156145d357610b17600160401b010260401c5b6108008216156145eb5761058c600160401b010260401c5b610400821615614603576102c6600160401b010260401c5b61020082161561461b57610163600160401b010260401c5b6101008216156146325760b1600160401b010260401c5b6080821615614648576059600160401b010260401c5b604082161561465e57602c600160401b010260401c5b6020821615614674576016600160401b010260401c5b601082161561468a57600b600160401b010260401c5b60088216156146a0576006600160401b010260401c5b60048216156146b6576003600160401b010260401c5b60028216156146cc576001600160401b010260401c5b60018216156146e2576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60405180606001604052806000815260200160008152602001600081525090565b6040518060e00160405280600081526020016000815260200161473b61475f565b81526020016000815260200160008152602001600081526020016000151581525090565b604051806040016040528060008152602001600081525090565b6040518061022001604052806147f06040518061014001604052806000801916815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200161481960405180606001604052806000815260200160008152602001600081525090565b81526020016148266148ce565b81526020016148336148a6565b8152602001614840614904565b815260200161484d6148a6565b815260200161485a61475f565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b03811182821017156149665761496661492e565b60405290565b604051608081016001600160401b03811182821017156149665761496661492e565b60405161018081016001600160401b03811182821017156149665761496661492e565b60405161010081016001600160401b03811182821017156149665761496661492e565b604051606081016001600160401b03811182821017156149665761496661492e565b60405161014081016001600160401b03811182821017156149665761496661492e565b604051601f8201601f191681016001600160401b0381118282101715614a4157614a4161492e565b604052919050565b6001600160a01b0381168114614a5e57600080fd5b50565b8035613f9c81614a49565b600060e08284031215614a7e57600080fd5b614a86614944565b90508135614a9381614a49565b81526020820135614aa381614a49565b60208201526040820135614ab681614a49565b60408201526060820135614ac981614a49565b6060820152614ada60808301614a61565b6080820152614aeb60a08301614a61565b60a0820152614afc60c08301614a61565b60c082015292915050565b600060808284031215614b1957600080fd5b614b2161496c565b90508135614b2e81614a49565b81526020820135614b3e81614a49565b60208201526040820135614b5181614a49565b60408201526060820135614b6481614a49565b606082015292915050565b60006001600160401b03821115614b8857614b8861492e565b5060051b60200190565b600082601f830112614ba357600080fd5b8135614bb6614bb182614b6f565b614a19565b8082825260208201915060208360051b860101925085831115614bd857600080fd5b602085015b83811015614bfe578035614bf081614a49565b835260209283019201614bdd565b5095945050505050565b803560098110613f9c57600080fd5b803560038110613f9c57600080fd5b60006101808284031215614c3957600080fd5b614c4161498e565b9050614c4c82614c08565b8152614c5a60208301614c17565b602082015260408281013590820152606080830135908201526080808301359082015260a0808301359082015260c0808301359082015260e080830135908201526101008083013590820152610120808301359082015261014080830135908201526101609182013591810191909152919050565b80358015158114613f9c57600080fd5b600060808284031215614cf157600080fd5b614cf961496c565b9050614d0482614ccf565b8152614d1260208301614ccf565b6020820152614d2360408301614ccf565b6040820152614b6460608301614ccf565b600082601f830112614d4557600080fd5b8135614d53614bb182614b6f565b8082825260208201915060208360051b860101925085831115614d7557600080fd5b602085015b83811015614bfe578035835260209283019201614d7a565b60006102408284031215614da557600080fd5b614dad61496c565b905081356001600160401b03811115614dc557600080fd5b82016101008185031215614dd857600080fd5b614de06149b1565b614de982614a61565b8152614df760208301614a61565b6020820152614e0860408301614a61565b6040820152614e1960608301614a61565b6060820152614e2a60808301614a61565b6080820152614e3b60a08301614a61565b60a0820152614e4c60c08301614a61565b60c082015260e08201356001600160401b03811115614e6a57600080fd5b614e7686828501614b92565b60e083015250825250614e8c8360208401614c26565b6020820152614e9f836101a08401614cdf565b60408201526102208201356001600160401b03811115614ebe57600080fd5b614eca84828501614d34565b60608301525092915050565b600060208284031215614ee857600080fd5b604051602081016001600160401b0381118282101715614f0a57614f0a61492e565b604052905080614f1983614ccf565b905292915050565b60008183036101c0811215614f3557600080fd5b614f3d6149d4565b91506060811215614f4d57600080fd5b614f556149d4565b8335614f6081614a49565b81526020840135614f7081614a49565b60208201526040840135614f8381614a49565b60408201528252610140605f1982011215614f9d57600080fd5b50614fa66149f6565b606083810135825260808085013560208085019190915260a080870135604086015260c0808801359486019490945260e0808801359386019390935261010080880135918601919091526101208088013594860194909452610140870135928501929092526101608601359184019190915261018085013591830191909152820152615036836101a08401614ed6565b604082015292915050565b803560028110613f9c57600080fd5b60006103a0828403121561506357600080fd5b61506b614944565b90506150778383614a6c565b81526150868360e08401614b07565b60208201526101608201356001600160401b038111156150a557600080fd5b6150b184828501614d92565b60408301525061018082013560608201526150d0836101a08401614f21565b608082015261036082013560a0820152614afc6103808301615041565b6000604082840312156150ff57600080fd5b604080519081016001600160401b03811182821017156151215761512161492e565b604052823581526020928301359281019290925250919050565b600060c0828403121561514d57600080fd5b6151556149d4565b905061516183836150ed565b815261517083604084016150ed565b602082015261503683608084016150ed565b60008060e0838503121561519557600080fd5b82356001600160401b038111156151ab57600080fd5b6151b785828601615050565b9250506151c7846020850161513b565b90509250929050565b60008060008061018085870312156151e757600080fd5b84356151f281614a49565b9350602085013561520281614a49565b92506152118660408701614b07565b91506152208660c0870161513b565b905092959194509250565b6000806060838503121561523e57600080fd5b82356001600160401b0381111561525457600080fd5b61526085828601615050565b9250506151c784602085016150ed565b6000806000806000806000610380888a03121561528c57600080fd5b873561529781614a49565b965060208801356152a781614a49565b95506152b68960408a01614f21565b94506152c6896102008a01614b07565b93506152d6896102808a0161513b565b92506152e56103408901614ccf565b91506152f46103608901614ccf565b905092959891949750929550565b6000815180845260005b818110156153285760208185018101518683018201520161530c565b506000602082860101526020601f19601f83011685010191505092915050565b831515815260a06020820152600061536360a0830185615302565b9050825160408301526020830151606083015260408301516080830152949350505050565b6000806000806000808688036102208112156153a357600080fd5b87356153ae81614a49565b96506153bd8960208a01614b07565b95506153cc8960a08a0161513b565b94506101608801356153dd81614a49565b93506153ec6101808901614ccf565b9250608061019f198201121561540157600080fd5b5061540a61496c565b6101a088013581526101c088013560208201526101e088013560408201526102009097013560608801525093969295509093909291565b6000806000806000610340868803121561545a57600080fd5b853561546581614a49565b94506154748760208801614b07565b93506154838760a0880161513b565b9250615493876101608801614f21565b94979396509194610320013592915050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000826154e0576154e06154a5565b600160ff1b8214600019841416156154fa576154fa6154bb565b500590565b60008261550e5761550e6154a5565b500490565b8082018281126000831280158216821582161715615533576155336154bb565b505092915050565b818103600083128015838313168383128216171561555b5761555b6154bb565b5092915050565b918252602082015260400190565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b6155b882825180518252602090810151910152565b602081810151805160408501529081015160608401525060400151805160808301526020015160a090910152565b6001600160a01b03858116825284166020820152610180810161560c6040830185615570565b611bc360c08301846155a3565b6001600160a01b038681168252851660208201526101a0810161563f6040830186615570565b61564c60c08301856155a3565b8215156101808301529695505050505050565b6000600160ff1b8201615674576156746154bb565b5060000390565b808202811582820484141761121a5761121a6154bb565b80820260008212600160ff1b841416156156ae576156ae6154bb565b818105831482151761121a5761121a6154bb565b6000602082840312156156d457600080fd5b5051919050565b6001600160a01b0392831681529116602082015260400190565b6080815260006157086080830187615302565b6020830195909552506040810192909252606090910152919050565b8082018082111561121a5761121a6154bb565b8181038181111561121a5761121a6154bb565b6001600160a01b0391909116815260200190565b60006020828403121561577057600080fd5b815161174781614a49565b6000806040838503121561578e57600080fd5b505080516020909101519092909150565b634e487b7160e01b600052602160045260246000fdfea264697066735822122001816216d36b781677541d9d282941e09404e8c34533d4bcc6284f9e6e05ef6964736f6c634300081d0033", + "numDeployments": 25, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"EmptySizeDeltaInTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidCollateralTokenForMarket\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"}],\"name\":\"InvalidPositionSizeValues\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"},{\"internalType\":\"int256\",\"name\":\"remainingCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsdForLeverage\",\"type\":\"int256\"}],\"name\":\"LiquidatablePosition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"positionSizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minPositionSizeUsd\",\"type\":\"uint256\"}],\"name\":\"MinPositionSize\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"executionPrice\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"positionSizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"priceImpactUsd\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"}],\"name\":\"NegativeExecutionPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"acceptablePrice\",\"type\":\"uint256\"}],\"name\":\"OrderNotFulfillableAtAcceptablePrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__Exp2InputTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"PRBMathUD60x18__LogInputTooSmall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivFixedPointOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"priceImpactUsd\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"}],\"name\":\"PriceImpactLargerThanOrderSize\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"UnableToGetCachedTokenPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"positionBorrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cumulativeBorrowingFactor\",\"type\":\"uint256\"}],\"name\":\"UnexpectedBorrowingFactor\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"usdDelta\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"longOpenInterest\",\"type\":\"uint256\"}],\"name\":\"UsdDeltaExceedsLongOpenInterest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"usdDelta\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"shortOpenInterest\",\"type\":\"uint256\"}],\"name\":\"UsdDeltaExceedsShortOpenInterest\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"eventEmitter\",\"type\":\"EventEmitter\"},{\"internalType\":\"contract MultichainVault\",\"name\":\"multichainVault\",\"type\":\"MultichainVault\"},{\"internalType\":\"contract OrderVault\",\"name\":\"orderVault\",\"type\":\"OrderVault\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"IOracle\"},{\"internalType\":\"contract ISwapHandler\",\"name\":\"swapHandler\",\"type\":\"ISwapHandler\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"}],\"internalType\":\"struct BaseOrderUtils.ExecuteOrderParamsContracts\",\"name\":\"contracts\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cancellationReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"callbackContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"uiFeeReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialCollateralToken\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"internalType\":\"struct Order.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"enum Order.OrderType\",\"name\":\"orderType\",\"type\":\"Order.OrderType\"},{\"internalType\":\"enum Order.DecreasePositionSwapType\",\"name\":\"decreasePositionSwapType\",\"type\":\"Order.DecreasePositionSwapType\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialCollateralDeltaAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"triggerPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"acceptablePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callbackGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"validFromTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"}],\"internalType\":\"struct Order.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"shouldUnwrapNativeToken\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isFrozen\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"autoCancel\",\"type\":\"bool\"}],\"internalType\":\"struct Order.Flags\",\"name\":\"flags\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"_dataList\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct Order.Props\",\"name\":\"order\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"orderKey\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"positionKey\",\"type\":\"bytes32\"},{\"internalType\":\"enum Order.SecondaryOrderType\",\"name\":\"secondaryOrderType\",\"type\":\"Order.SecondaryOrderType\"}],\"internalType\":\"struct PositionUtils.UpdatePositionParams\",\"name\":\"params\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"}],\"name\":\"getExecutionPriceForDecrease\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract EventEmitter\",\"name\":\"eventEmitter\",\"type\":\"EventEmitter\"},{\"internalType\":\"contract MultichainVault\",\"name\":\"multichainVault\",\"type\":\"MultichainVault\"},{\"internalType\":\"contract OrderVault\",\"name\":\"orderVault\",\"type\":\"OrderVault\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"IOracle\"},{\"internalType\":\"contract ISwapHandler\",\"name\":\"swapHandler\",\"type\":\"ISwapHandler\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"}],\"internalType\":\"struct BaseOrderUtils.ExecuteOrderParamsContracts\",\"name\":\"contracts\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cancellationReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"callbackContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"uiFeeReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialCollateralToken\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"swapPath\",\"type\":\"address[]\"}],\"internalType\":\"struct Order.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"enum Order.OrderType\",\"name\":\"orderType\",\"type\":\"Order.OrderType\"},{\"internalType\":\"enum Order.DecreasePositionSwapType\",\"name\":\"decreasePositionSwapType\",\"type\":\"Order.DecreasePositionSwapType\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialCollateralDeltaAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"triggerPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"acceptablePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callbackGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"validFromTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"}],\"internalType\":\"struct Order.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"shouldUnwrapNativeToken\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isFrozen\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"autoCancel\",\"type\":\"bool\"}],\"internalType\":\"struct Order.Flags\",\"name\":\"flags\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"_dataList\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct Order.Props\",\"name\":\"order\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"orderKey\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"positionKey\",\"type\":\"bytes32\"},{\"internalType\":\"enum Order.SecondaryOrderType\",\"name\":\"secondaryOrderType\",\"type\":\"Order.SecondaryOrderType\"}],\"internalType\":\"struct PositionUtils.UpdatePositionParams\",\"name\":\"params\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"}],\"name\":\"getExecutionPriceForIncrease\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"sizeDeltaUsd\",\"type\":\"uint256\"}],\"name\":\"getPositionPnlUsd\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"shouldValidateMinCollateralUsd\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"forLiquidation\",\"type\":\"bool\"}],\"name\":\"isPositionLiquidatable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"remainingCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateralUsdForLeverage\",\"type\":\"int256\"}],\"internalType\":\"struct PositionUtils.IsPositionLiquidatableInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"internalType\":\"contract IReferralStorage\",\"name\":\"referralStorage\",\"type\":\"IReferralStorage\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"}],\"internalType\":\"struct Position.Addresses\",\"name\":\"addresses\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"sizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sizeInTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"pendingImpactAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"borrowingFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fundingFeeAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"longTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortTokenClaimableFundingAmountPerSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"increasedAtTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decreasedAtTime\",\"type\":\"uint256\"}],\"internalType\":\"struct Position.Numbers\",\"name\":\"numbers\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct Position.Flags\",\"name\":\"flags\",\"type\":\"tuple\"}],\"internalType\":\"struct Position.Props\",\"name\":\"position\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"shouldValidateMinPositionSize\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"shouldValidateMinCollateralUsd\",\"type\":\"bool\"}],\"name\":\"validatePosition\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStore\",\"name\":\"dataStore\",\"type\":\"DataStore\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"marketToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"indexToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"longToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"shortToken\",\"type\":\"address\"}],\"internalType\":\"struct Market.Props\",\"name\":\"market\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"indexTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"longTokenPrice\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"internalType\":\"struct Price.Props\",\"name\":\"shortTokenPrice\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketUtils.MarketPrices\",\"name\":\"prices\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"positionSizeInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"positionCollateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"realizedPnlUsd\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"openInterestDelta\",\"type\":\"int256\"}],\"internalType\":\"struct PositionUtils.WillPositionCollateralBeSufficientValues\",\"name\":\"values\",\"type\":\"tuple\"}],\"name\":\"willPositionCollateralBeSufficient\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMathUD60x18__Exp2InputTooBig(uint256)\":[{\"notice\":\"Emitted when the input is greater than 192.\"}],\"PRBMathUD60x18__LogInputTooSmall(uint256)\":[{\"notice\":\"Emitted when the input is less than 1.\"}],\"PRBMath__MulDivFixedPointOverflow(uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/position/PositionUtils.sol\":\"PositionUtils\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0xa7a5a10c9321e7372bc6a8c11da319e6421ed5c0676810a1c8ec30c30f730331\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x6157eb610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100775760003560e01c8063610e3cb91461007c5780637396d38c146100be57806381db61b8146100e0578063a6dcd97614610110578063d7e3321114610132578063dac6485714610145578063e22de7931461016f575b600080fd5b61008f61008a366004615182565b61019d565b6040805195865260208601949094529284019190915260608301521515608082015260a0015b60405180910390f35b8180156100ca57600080fd5b506100de6100d93660046151d0565b61045a565b005b6100f36100ee36600461522b565b6105ad565b6040805193845260208401929092521515908201526060016100b5565b61012361011e366004615270565b6106f5565b6040516100b593929190615348565b6100de610140366004615270565b610bbf565b610158610153366004615388565b610dd7565b6040805192151583526020830191909152016100b5565b61018261017d366004615441565b610ea3565b604080519384526020840192909252908201526060016100b5565b60008060008060006101b88760400151602001516040015190565b6000036101f05760008060006101df6101d78b60800151604001515190565b8a5190611203565b600094509450945094509450610450565b6102246040518060a00160405280600081526020016000815260200160008152602001600015158152602001600081525090565b604080516080810182528951516001600160a01b031681526020808b0151818301528a83015101518201516102829282019061026490611220565b611220565b81526020016102798b60400151604001515190565b1515905261128e565b1515606083015280825288515160208a01515160408b01516102b393906102ae90602001516040015190565b61134c565b808252600012156102e3578651602001516102cd90611220565b81516102d991906154d1565b60208201526102f8565b80518751516102f29190611398565b60208201525b608088015160400151511561033557865160200151604089015161032190602001516040015190565b61032b91906154ff565b6040820152610359565b61035361034b8960400151602001516040015190565b88515161140c565b60408201525b600061036b8960800151604001515190565b156103935781602001516103828360400151611220565b61038c9190615513565b90506103b2565b81602001516103a58360400151611220565b6103af919061553b565b90505b60008112156103ed57815160408a8101516020015101516040516378320e4960e11b81526004016103e4929190615562565b60405180910390fd5b6104286104038a60400151602001516040015190565b61040c8361142f565b60408c01516020015160a0015160808d01516040015151611481565b6080830181905282516020840151604085015160609095015191995097509295509350909150505b9295509295909350565b60405163034aadf760e61b8152739080f8A35Da53F4200a68533FB1dC1cA05357bDB9063d2ab7dc0906104979087908790879087906004016155e6565b60006040518083038186803b1580156104af57600080fd5b505af41580156104c3573d6000803e3d6000fd5b5050604051631450a87960e01b8152739080f8A35Da53F4200a68533FB1dC1cA05357bDB9250631450a8799150610507908790879087908790600190600401615619565b60006040518083038186803b15801561051f57600080fd5b505af4158015610533573d6000803e3d6000fd5b5050604051631450a87960e01b8152739080f8A35Da53F4200a68533FB1dC1cA05357bDB9250631450a8799150610577908790879087908790600090600401615619565b60006040518083038186803b15801561058f57600080fd5b505af41580156105a3573d6000803e3d6000fd5b5050505050505050565b6000806000806105c68660400151602001516040015190565b9050806000036105fb5760006105ed6105e58860800151604001515190565b879015611203565b6000935093509350506106ee565b610621604051806060016040528060008152602001600015158152602001600081525090565b604080516080810182528851516001600160a01b031681526020808a01519082015261067091810161065285611220565b61065b9061565f565b81526020016102798a60400151604001515190565b1515602080840191909152818352885151908901515160408a015161069f93906102ae90602001516040015190565b80825260808801516020808201518051908201516040808d01519093015160a001519290930151516106d6948b94929388926114fc565b60408201819052815160209092015191955093509150505b9250925092565b600060606107016146f9565b61070961471a565b6107116146f9565b6107248c8a8a8d61017d8f602001515190565b5050825261073e6107378b516040015190565b8a8a6116ad565b60408301819052516107558b602001516040015190565b61075f919061567b565b606083015261077361025f8b602001515190565b61077c9061565f565b8260800181815250506107be60405180608001604052808e6001600160a01b031681526020018b8152602001846080015181526020016102798d604001515190565b151560c084015260a08301819052895160208c0151516107e0928f929161134c565b60a083015260006107f68b602001516060015190565b136108225787516020015161080a90611220565b60208b01516060015161081d9190615692565b610841565b87515161082e90611220565b60208b0151606001516108419190615692565b8260a0018181516108529190615513565b90525060a082015160001361086d57600060a08301526108bb565b600061087d8d8b6000015161174e565b9050600061089961025f6108938e602001515190565b846117c7565b6108a29061565f565b9050808460a0015112156108b85760a084018190525b50505b60006040518061014001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c8152602001846040015181526020018460c00151151581526020018b604001516001600160a01b031681526020018b606001516001600160a01b031681526020016109358d602001515190565b81526000602082018190526040909101819052909150610954826117e0565b90506000846040015160000151826101e00151610971919061567b565b905061097c81611220565b60a08601518651606088015161099190611220565b61099b9190615513565b6109a59190615513565b6109af919061553b565b845288156109cf576109c58f8d60000151611a4f565b60208601526109e3565b6109dd8f8d60000151611a69565b60208601525b6109ff61025f6109f58f602001515190565b87602001516117c7565b60408501528915610b0e57610ac78f6001600160a01b031663bd02d0f5604051602001610a529060208082526012908201527113525397d0d3d31310551154905317d554d160721b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610a8691815260200190565b602060405180830381865afa158015610aa3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025f91906156c2565b6020850181905284511215610b0e57505060408051808201909152600e81526d1b5a5b8818dbdb1b185d195c985b60921b6020820152600196509450909250610bb2915050565b8351600012610b4457505060408051808201909152600381526203c20360ec1b6020820152600196509450909250610bb2915050565b604084015184511215610b9657505060408051808201909152601b81527a6d696e20636f6c6c61746572616c20666f72206c6576657261676560281b6020820152600196509450909250610bb2915050565b5050604080516020810190915260008082529650945090925050505b9750975097945050505050565b6020850151511580610bd657506020808601510151155b15610c0157602085810151805191015160405163bff65b3f60e01b81526103e4929190600401615562565b8351604051630ef68b4760e11b8152739080f8A35Da53F4200a68533FB1dC1cA05357bDB91631ded168e91610c3a918b916004016156db565b60006040518083038186803b158015610c5257600080fd5b505af4158015610c66573d6000803e3d6000fd5b50505050610c7f84610c7a87516040015190565b611a83565b8115610d7d576000876001600160a01b031663bd02d0f5604051602001610ccf9060208082526015908201527413525397d413d4d2551253d397d4d2569157d554d1605a1b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610d0391815260200190565b602060405180830381865afa158015610d20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4491906156c2565b905080610d5387602001515190565b1015610d7b57602086015151816040516342f7d98d60e11b81526004016103e4929190615562565b505b6000806000610d928a8a8a8a8a8960006106f5565b9250925092508215610dcb5781816000015182602001518360400151604051631782422160e31b81526004016103e494939291906156f5565b50505050505050505050565b6000806000610de78689896116ad565b90506000610df88260000151611220565b610e058660200151611220565b610e0f9190615692565b9050600085604001511215610e30576040850151610e2d9082615513565b90505b6000811215610e4657600093509150610e989050565b6000610e588b8b88606001518a611ab3565b90506000610e6a8c8c60000151611a69565b905081811115610e78578091505b6000610e8b61025f8960000151856117c7565b8412159650929450505050505b965096945050505050565b6000806000610f1560405180610180016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610f30610f2688604001515190565b8951906000611aec565b9050610f4f81610f4589602090810151015190565b61025f919061567b565b8252604087015151610f7b578151610f6c61025f89602001515190565b610f76919061553b565b610f96565b610f8a61025f88602001515190565b8251610f96919061553b565b60208301819052604083018190526000121561111557604087015151610fc0578860600151610fc6565b88604001515b6001600160a01b031660608301819052610fe3908b908b90611b25565b6080830152604087015151610ffd57604088015151611004565b6020880151515b60a08301819052608083015161101a919061567b565b60c0830152875161103c908b908b906110358b604001515190565b6001611bcc565b60e083015288516040880151516110b2918c918560e001518660c00151604051602001611097906020808252601a90820152794d41585f504e4c5f464143544f525f464f525f5452414445525360301b604082015260600190565b60405160208183030381529060405280519060200120611c58565b610100830181905260e0830151148015906110d257506000826101000151135b80156110e2575060008260e00151135b156111155761110f6110f7836020015161142f565b83610100015161110a8560e0015161142f565b611ca8565b60208301525b8561112288602001515190565b0361113b5760208088015101515b610120830152611195565b6040870151511561116e576111308661115989602090810151015190565b611163919061567b565b60208901515161140c565b602087810151805191015161118490889061567b565b61118e91906154ff565b6101208301525b6111b782602001518361012001516111b28a602090810151015190565b611ce8565b61014083015260408201516101208301516020808a015101516111db929190611ce8565b610160830181905261014083015161012090930151929b909a50919850909650505050505050565b600081611211578251611217565b82602001515b90505b92915050565b60006001600160ff1b0382111561128a5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016103e4565b5090565b600080600061129c84611cf5565b90506000806112b8866000015187602001516000015185611d38565b91509150600082126112cf57909590945092505050565b6000806112e88860000151896020015160200151611e62565b91509150816112fe575091969095509350505050565b600061130a8983611f78565b90506000806113268b600001518c602001516000015185611d38565b9150915086821261133857868661133b565b81815b995099505050505050505050915091565b60008083121561135d575081611390565b600061136b86866001611ff2565b9050600061137c61025f85846117c7565b90508085131561138a578094505b84925050505b949350505050565b6000808312156113da576113ab82611220565b6113b483611220565b6113be908561553b565b6113c9906001615513565b6113d391906154d1565b905061121a565b6113e382611220565b60016113ee84611220565b6113f89086615513565b611402919061553b565b61121791906154d1565b600081600161141b8286615724565b6114259190615737565b61121791906154ff565b60008082121561128a5760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016103e4565b6000836000036114a457604051633df4253160e01b815260040160405180910390fd5b60006114b085876154ff565b90508280156114bf5750838111155b806114d35750821580156114d35750838110155b156114df579050611390565b808460405163e09ad0e960e01b81526004016103e4929190615562565b600061152260405180606001604052806000815260200160008152602001600081525090565b61152d898415611203565b808252602082015285158015906115445750600087115b15611648578261155c576115578561565f565b61155e565b845b60408201819052600013801561158857508561158682604001516115819061565f565b61142f565b115b156115ae578060400151866040516378320e4960e11b81526004016103e4929190615562565b60006115b987611220565b6115c88a84604001518b611ca8565b6115d291906154d1565b90506000816115e48460000151611220565b6115ee9190615513565b90506000811215611637578251604080850151905163cc32db9960e01b8152600481018490526024810192909252604482018c905260648201526084810189905260a4016103e4565b6116408161142f565b602084015250505b828015611659575083816020015110155b80611671575082158015611671575083816020015111155b15611681576020015190506116a2565b80602001518460405163e09ad0e960e01b81526004016103e4929190615562565b979650505050505050565b6116b561475f565b82604001516001600160a01b0316846001600160a01b0316036116dd57506020810151611747565b82606001516001600160a01b0316846001600160a01b03160361170557506040810151611747565b82602001516001600160a01b0316846001600160a01b03160361172a57508051611747565b8251604051635f2394d160e11b81526103e49186916004016156db565b9392505050565b6000826001600160a01b031663bd02d0f561176884612019565b6040518263ffffffff1660e01b815260040161178691815260200190565b602060405180830381865afa1580156117a3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121791906156c2565b6000611217838368327cb2734119d3b7a9601e1b6120bb565b6117e8614779565b6000611822836000015184602001518560600151866080015161180e8860400151515190565b604089015151602001518960e001516120c8565b9050600061183884600001518560400151612552565b905061184d84600001518560600151836125df565b6060830152610120840151156118835783516040850151516020015161187d91908660e0015187606001516126ee565b60a08301525b8160a00151606001518260a00151602001518360600151606001518460600151602001518561018001516118b79190615724565b6118c19190615737565b6118cb9190615724565b6118d59190615737565b61016083015260a082015160609081015181840151909101516118f89190615724565b826101400181815161190a9190615724565b9052508351604080860151805160208101519083015191909201515161193293929190612894565b604080840151606001919091528451908501515160200151611962919060a087015160408089015101515161290f565b604080840151608001919091528451908501515160200151611992919060c087015160408089015101515161290f565b826040015160a00181815250506119b18260400151856040015161292b565b60408301528351606085015160e08601516101008701516119d4939291906129a7565b82608001819052508161020001518260800151604001518360a0015160200151846060015160200151856101a00151611a0d9190615724565b611a179190615724565b611a219190615724565b611a2b9190615737565b6101c08301819052604083015151611a4291615724565b6101e08301525092915050565b6000826001600160a01b031663bd02d0f561176884612a0f565b6000826001600160a01b031663bd02d0f561176884612a60565b611a8d8282612a9b565b611aaf5781516040516341ce349f60e11b81526103e4919083906004016156db565b5050565b600080611ac1868685612ad4565b9050611acd8185612b27565b90506000611ae087876000015186612b57565b90506116a282826117c7565b60008215611b0d5781611b00578351611b06565b83602001515b9050611747565b81611b1c578360200151611390565b50509051919050565b600080611b3a84604001518560600151612bd1565b905080856001600160a01b031663bd02d0f5611b5a876000015187612c00565b6040518263ffffffff1660e01b8152600401611b7891815260200190565b602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906156c2565b611bc391906154ff565b95945050505050565b600080611bdd61025f888887612ad4565b90506000611bec888887612c88565b9050811580611bf9575080155b15611c0957600092505050611bc3565b6000611c16878787611aec565b90506000611c2761025f838561567b565b9050600087611c3f57611c3a828661553b565b611c49565b611c49858361553b565b9b9a5050505050505050505050565b600080841215611c69575082611c9e565b6000611c7788848989612ccf565b90506000611c8861025f86846117c7565b9050808613611c975785611c99565b805b925050505b9695505050505050565b600080611cbe85611cb886612ceb565b856120bb565b905060008413611cdf57611cd181611220565b611cda9061565f565b611bc3565b611bc381611220565b6000611390838584611ca8565b611cfd6148a6565b6000611d13836000015184602001516001612ad4565b90506000611d2b846000015185602001516000612ad4565b9050611390848383612cfc565b6000806000611d4f84600001518560200151612dee565b90506000611d6585604001518660600151612dee565b6060860151604087015160208801518851939450909211159111151460006001600160a01b03891663bd02d0f5611d9b8a612e10565b6040518263ffffffff1660e01b8152600401611db991815260200190565b602060405180830381865afa158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa91906156c2565b90508383108215611e30576000611e128b8b84612e53565b9050611e2086868386612e62565b8297509750505050505050611e5a565b600080611e3d8c8c612ea0565b91509150611e4e8787848488612fb4565b98509196505050505050505b935093915050565b6000806000846001600160a01b031663a6ed563e611e7f86612ffd565b6040518263ffffffff1660e01b8152600401611e9d91815260200190565b602060405180830381865afa158015611eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ede91906156c2565b905080611ef2576000809250925050611f71565b6001856001600160a01b031663dc97d962611f0c84613033565b6040518263ffffffff1660e01b8152600401611f2a91815260200190565b602060405180830381865afa158015611f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6b91906156c2565b92509250505b9250929050565b611f806148a6565b6000806000841315611f9c57611f958461142f565b9050611fab565b611fa86115818561565f565b91505b600085604001511215611fe7576000611fcb86604001516115819061565f565b9050611fd78184615724565b9250611fe38183615724565b9150505b611bc3858383612cfc565b6000806000612001868661309e565b91509150836120105780611c9e565b50949350505050565b6000604051602001612070906020808252602b908201527f4d41585f504f534954494f4e5f494d504143545f464143544f525f464f525f4c60408201526a49515549444154494f4e5360a81b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038416908201526060015b604051602081830303815290604052805190602001209050919050565b600061139084848461313a565b6120d0614779565b6120d8614779565b60c0810187905280516001600160a01b03861660409091015260006120fe8a8a88613224565b865160c081019290925260808201929092526001600160a01b039283166020820152929092529091508a1663bd02d0f5612138878a613563565b6040518263ffffffff1660e01b815260040161215691815260200190565b602060405180830381865afa158015612173573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219791906156c2565b60e083018190528851906121ac9086906117c7565b6121b691906154ff565b6101a08301526001600160a01b038a1663bd02d0f56121d4886135d6565b6040518263ffffffff1660e01b81526004016121f291815260200190565b602060405180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223391906156c2565b602083018051919091525151156122fa57896001600160a01b031663bd02d0f561226484602001516000015161360b565b6040518263ffffffff1660e01b815260040161228291815260200190565b602060405180830381865afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c391906156c2565b6020808401805182019290925290510151156122fa576122f0826101a001518360200151602001516117c7565b6020830151604001525b815151156123f057815160808082015160a090920191909152825160c08101519101516123279190615724565b825160600152815160c00151602080840151015111156123925781516060015160208084015101511161237157602080830151015182516060015161236c9190615737565b612373565b805b825160a0908101919091528251015181111561239257815160a0018190525b6123a9826101a00151836000015160a001516117c7565b825161012001526101a0820151825160c001516123c691906117c7565b825161010090810191909152825190810151610120909101516123e99190615724565b825160e001525b8151610100015160208301516040015111612411578151610100015161241b565b8160200151604001515b6102008301819052825161012001516101a084015161243a9190615737565b6124449190615737565b6101008301526040516001600160a01b038b169063bd02d0f59061249b906020016020808252601c908201527b2827a9a4aa24a7a72fa322a2afa922a1a2a4ab22a92fa320a1aa27a960211b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016124cf91815260200190565b602060405180830381865afa1580156124ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251091906156c2565b6101208301819052610100830151612527916117c7565b610140830181905261010083015161253f9190615737565b6101808301525098975050505050505050565b6000806125708461256585516020015190565b604086015151613644565b90508061258284602001516080015190565b11156125ad5760208301516080015181604051634cd96ac160e11b81526004016103e4929190615562565b60006125be84602001516080015190565b6125c89083615737565b9050611bc36125d985602001515190565b826117c7565b6125e76148a6565b6125ef6148a6565b82815283516125fe90846154ff565b816020018181525050846001600160a01b031663bd02d0f5604051602001612657906020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161268b91815260200190565b602060405180830381865afa1580156126a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126cc91906156c2565b6040820181905260208201516126e1916117c7565b6060820152949350505050565b6126f66148a6565b6126fe6148a6565b6000866001600160a01b031663bd02d0f56127188861365f565b6040518263ffffffff1660e01b815260040161273691815260200190565b602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277791906156c2565b90508060000361278957509050611390565b61279385826117c7565b80835284516127a2919061140c565b826020018181525050866001600160a01b031663bd02d0f56040516020016127fb906020808252601f908201527f4c49515549444154494f4e5f4645455f52454345495645525f464143544f5200604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161282f91815260200190565b602060405180830381865afa15801561284c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287091906156c2565b604083018190526020830151612885916117c7565b60608301525095945050505050565b6000846001600160a01b031663bd02d0f56128b086868661369b565b6040518263ffffffff1660e01b81526004016128ce91815260200190565b602060405180830381865afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc391906156c2565b6000846001600160a01b031663bd02d0f56128b086868661373c565b6129336148ce565b612957836060015161294a846020015160a0015190565b6020850151516001613789565b8352608083015161297e90612971846020015160c0015190565b6020850151516000613789565b602084015260a083015161299b90612971846020015160e0015190565b60408401525090919050565b6129af614904565b6129b7614904565b6001600160a01b0383166129cc579050611390565b6001600160a01b03831681526129e286846137c0565b602082018190528551906129f79086906117c7565b612a0191906154ff565b604082015295945050505050565b60006040516020016120709060208082526025908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4c495155494460408201526420aa24a7a760d91b606082015260800190565b60006040516020016120709060208082526015908201527426a4a72fa1a7a62620aa22a920a62fa320a1aa27a960591b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614806112175750506060909101516001600160a01b0391821691161490565b600080612ae984604001518560600151612bd1565b90506000612b0286866000015187604001518786613906565b90506000612b1b87876000015188606001518887613906565b90506116a28183615724565b600080821315612b4457612b3a82612ceb565b6113d39084615724565b612b4d82612ceb565b6112179084615737565b6000836001600160a01b031663bd02d0f5612b72858561398c565b6040518263ffffffff1660e01b8152600401612b9091815260200190565b602060405180830381865afa158015612bad573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139091906156c2565b6000816001600160a01b0316836001600160a01b031614612bf3576001612bf6565b60025b60ff169392505050565b6000604051602001612c31906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b600080612c9d84604001518560600151612bd1565b90506000612cb6868660000151876040015187866139ea565b90506000612b1b878760000151886060015188876139ea565b6000846001600160a01b031663bd02d0f56128b0868686613a07565b60008082121561128a575060000390565b612d046148a6565b60608401518390839015612d705760008660400151128015612d35575084612d3387604001516115819061565f565b115b15612d5b5785604001518560405163756d7c9d60e11b81526004016103e4929190615562565b612d69858760400151612b27565b9150612dca565b60008660400151128015612d93575083612d9187604001516115819061565f565b115b15612db95785604001518460405163022bc34560e61b81526004016103e4929190615562565b612dc7848760400151612b27565b90505b60408051608081018252958652602086019490945292840152506060820152919050565b6000818311612e0657612e018383615737565b611217565b6112178284615737565b6000604051602001612070906020808252601f908201527f504f534954494f4e5f494d504143545f4558504f4e454e545f464143544f5200604082015260600190565b60008060006120018686612ea0565b600084841081612e86612e76888787613a7b565b612e81888888613a7b565b612dee565b90506000612e948284613a94565b98975050505050505050565b6000806000846001600160a01b031663bd02d0f5612ebf866001613ab7565b6040518263ffffffff1660e01b8152600401612edd91815260200190565b602060405180830381865afa158015612efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1e91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613ab7565b6040518263ffffffff1660e01b8152600401612f5a91815260200190565b602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906156c2565b905080821115612fa9578091505b909590945092505050565b600080612fc2878685613a7b565b90506000612fd1878686613a7b565b90506000612fdf8383612dee565b90506000612fef82848611613a94565b9a9950505050505050505050565b60006040516020016120709060208082526010908201526f1592549515505317d513d2d15397d25160821b604082015260600190565b6000604051602001613076906020808252601f908201527f5649525455414c5f494e56454e544f52595f464f525f504f534954494f4e5300604082015260600190565b604051602081830303815290604052805190602001208260405160200161209e929190615562565b6000806000846001600160a01b031663bd02d0f56130bd866001613af3565b6040518263ffffffff1660e01b81526004016130db91815260200190565b602060405180830381865afa1580156130f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061311c91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613af3565b60008080600019858709858702925082811083820303915050806000036131745783828161316a5761316a6154a5565b0492505050611747565b8084116131bb5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016103e4565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000808080806001600160a01b03871661324c57506000935083925082915081905080613558565b6040516310ae4b6b60e31b81526000906001600160a01b038916906385725b589061327b908a9060040161574a565b602060405180830381865afa158015613298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132bc91906156c2565b90506000808080841561350a576040516306459e2360e51b8152600481018690526001600160a01b038d169063c8b3c46090602401602060405180830381865afa15801561330e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613332919061575e565b935060008c6001600160a01b0316631582a018866040518263ffffffff1660e01b8152600401613362919061574a565b602060405180830381865afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a391906156c2565b60405163039af9eb60e01b8152600481018290529091506001600160a01b038e169063039af9eb906024016040805180830381865afa1580156133ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061340e919061577b565b90945092506001600160a01b038e1663bd02d0f561342b83613b33565b6040518263ffffffff1660e01b815260040161344991815260200190565b602060405180830381865afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a91906156c2565b915060008d6001600160a01b03166371a6a790876040518263ffffffff1660e01b81526004016134ba919061574a565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb91906156c2565b90508015613507578093505b50505b600061352b61271061351c858761567b565b61352691906154ff565b613b74565b9050600061353885613b74565b905060006135468383615737565b979c50959a5095985096509450505050505b939792965093509350565b600060405160200161359c906020808252601390820152722827a9a4aa24a7a72fa322a2afa320a1aa27a960691b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038516908201528215156060820152608001612c6a565b6000604051602001612070906020808252600f908201526e282927afaa2920a222a92faa24a2a960891b604082015260600190565b600060405160200161307690602080825260139082015272282927afa224a9a1a7aaa72a2fa320a1aa27a960691b604082015260600190565b6000836001600160a01b031663bd02d0f5612b728585613b99565b6000604051602001612070906020808252601690820152752624a8aaa4a220aa24a7a72fa322a2afa320a1aa27a960511b604082015260600190565b60006040516020016136dc906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016136dc9060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b6000806137968587615737565b9050611c9e84826137ba66038d7ea4c6800068327cb2734119d3b7a9601e1b61567b565b86613bda565b600080836001600160a01b031663bd02d0f56040516020016138079060208082526011908201527026a0ac2faaa4afa322a2afa320a1aa27a960791b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161383b91815260200190565b602060405180830381865afa158015613858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387c91906156c2565b90506000846001600160a01b031663bd02d0f561389886613c01565b6040518263ffffffff1660e01b81526004016138b691815260200190565b602060405180830381865afa1580156138d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f791906156c2565b90508181106113905781611bc3565b600081866001600160a01b031663bd02d0f5613923888888613c34565b6040518263ffffffff1660e01b815260040161394191815260200190565b602060405180830381865afa15801561395e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398291906156c2565b611c9e91906154ff565b600060405160200161359c9060208082526032908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4f50454e5f49604082015271272a22a922a9aa2fa6aaa62a24a82624a2a960711b606082015260800190565b600081866001600160a01b031663bd02d0f5613923888888613c67565b6000604051602001613a3b906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a00161371d565b600080613a888584613ca4565b9050611bc381856117c7565b60008115613aa5576113d383611220565b613aae83611220565b6113d39061565f565b600060405160200161359c906020808252601690820152752827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960511b604082015260600190565b600060405160200161359c906020808252601a908201527926a0ac2fa827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960311b604082015260600190565b6000604051602001613076906020808252601b908201527a26a4a72fa0a32324a624a0aa22afa922aba0a9222fa320a1aa27a960291b604082015260600190565b6000612710613b8f68327cb2734119d3b7a9601e1b8461567b565b61121a91906154ff565b600060405160200161359c906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b60008115613bf657613bef8585856001613d03565b9050611390565b611bc385858561313a565b6000604051602001612070906020808252600d908201526c2aa4afa322a2afa320a1aa27a960991b604082015260600190565b60006040516020016136dc906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b60006040516020016136dc906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b600068327cb2734119d3b7a9601e1b831015613cc25750600061121a565b68327cb2734119d3b7a9601e1b8203613cdc57508161121a565b6000613cf8613cea85613d54565b613cf385613d54565b613d65565b905061139081613da5565b600080613d1186868661313a565b90506001836002811115613d2757613d2761579f565b148015613d44575060008480613d3f57613d3f6154a5565b868809115b15611bc357611c9e600182615724565b600061121a64e8d4a51000836154ff565b600082600003613d8b578115613d7c5760006113d3565b50670de0b6b3a764000061121a565b611217613da0613d9a85613db6565b84613e6c565b613e78565b600061121a64e8d4a510008361567b565b6000670de0b6b3a7640000821015613de457604051633621413760e21b8152600481018390526024016103e4565b6000613df9670de0b6b3a76400008404613ebe565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff198101613e22575050919050565b6706f05b59d3b200005b8015613e6457670de0b6b3a7640000828002049150671bc16d674ec800008210613e5c579283019260019190911c905b60011c613e2c565b505050919050565b60006112178383613fa1565b6000680a688906bd8b0000008210613ea657604051634a4f26f160e01b8152600481018390526024016103e4565b670de0b6b3a7640000604083901b0461174781614067565b6000600160801b8210613ede57608091821c91613edb9082615724565b90505b600160401b8210613efc57604091821c91613ef99082615724565b90505b600160201b8210613f1a57602091821c91613f179082615724565b90505b620100008210613f3757601091821c91613f349082615724565b90505b6101008210613f5357600891821c91613f509082615724565b90505b60108210613f6e57600491821c91613f6b9082615724565b90505b60048210613f8957600291821c91613f869082615724565b90505b60028210613f9c5761121a600182615724565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110613fe55760405163698d9a0160e11b8152600481018290526024016103e4565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff82119050826000036140235780670de0b6b3a764000085040194505050505061121a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b8216156140875768016a09e667f3bcc9090260401c5b6001603e1b8216156140a2576801306fe0a31b7152df0260401c5b6001603d1b8216156140bd576801172b83c7d517adce0260401c5b6001603c1b8216156140d85768010b5586cf9890f62a0260401c5b6001603b1b8216156140f3576801059b0d31585743ae0260401c5b6001603a1b82161561410e57680102c9a3e778060ee70260401c5b600160391b8216156141295768010163da9fb33356d80260401c5b600160381b82161561414457680100b1afa5abcbed610260401c5b600160371b82161561415f5768010058c86da1c09ea20260401c5b600160361b82161561417a576801002c605e2e8cec500260401c5b600160351b82161561419557680100162f3904051fa10260401c5b600160341b8216156141b0576801000b175effdc76ba0260401c5b600160331b8216156141cb57680100058ba01fb9f96d0260401c5b600160321b8216156141e65768010002c5cc37da94920260401c5b600160311b821615614201576801000162e525ee05470260401c5b600160301b82161561421c5768010000b17255775c040260401c5b6001602f1b821615614237576801000058b91b5bc9ae0260401c5b6001602e1b82161561425257680100002c5c89d5ec6d0260401c5b6001602d1b82161561426d5768010000162e43f4f8310260401c5b6001602c1b82161561428857680100000b1721bcfc9a0260401c5b6001602b1b8216156142a35768010000058b90cf1e6e0260401c5b6001602a1b8216156142be576801000002c5c863b73f0260401c5b600160291b8216156142d957680100000162e430e5a20260401c5b600160281b8216156142f4576801000000b1721835510260401c5b600160271b82161561430f57680100000058b90c0b490260401c5b600160261b82161561432a5768010000002c5c8601cc0260401c5b600160251b821615614345576801000000162e42fff00260401c5b600160241b8216156143605768010000000b17217fbb0260401c5b600160231b82161561437b576801000000058b90bfce0260401c5b600160221b82161561439657680100000002c5c85fe30260401c5b600160211b8216156143b15768010000000162e42ff10260401c5b600160201b8216156143cc57680100000000b17217f80260401c5b63800000008216156143e75768010000000058b90bfc0260401c5b6340000000821615614402576801000000002c5c85fe0260401c5b632000000082161561441d57680100000000162e42ff0260401c5b6310000000821615614438576801000000000b17217f0260401c5b630800000082161561445357680100000000058b90c00260401c5b630400000082161561446e5768010000000002c5c8600260401c5b6302000000821615614489576801000000000162e4300260401c5b63010000008216156144a45768010000000000b172180260401c5b628000008216156144be576801000000000058b90c0260401c5b624000008216156144d857680100000000002c5c860260401c5b622000008216156144f25768010000000000162e430260401c5b6210000082161561450c57680100000000000b17210260401c5b620800008216156145265768010000000000058b910260401c5b62040000821615614540576801000000000002c5c80260401c5b6202000082161561455a57680100000000000162e40260401c5b620100008216156145735761b172600160401b010260401c5b61800082161561458b576158b9600160401b010260401c5b6140008216156145a357612c5d600160401b010260401c5b6120008216156145bb5761162e600160401b010260401c5b6110008216156145d357610b17600160401b010260401c5b6108008216156145eb5761058c600160401b010260401c5b610400821615614603576102c6600160401b010260401c5b61020082161561461b57610163600160401b010260401c5b6101008216156146325760b1600160401b010260401c5b6080821615614648576059600160401b010260401c5b604082161561465e57602c600160401b010260401c5b6020821615614674576016600160401b010260401c5b601082161561468a57600b600160401b010260401c5b60088216156146a0576006600160401b010260401c5b60048216156146b6576003600160401b010260401c5b60028216156146cc576001600160401b010260401c5b60018216156146e2576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60405180606001604052806000815260200160008152602001600081525090565b6040518060e00160405280600081526020016000815260200161473b61475f565b81526020016000815260200160008152602001600081526020016000151581525090565b604051806040016040528060008152602001600081525090565b6040518061022001604052806147f06040518061014001604052806000801916815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200161481960405180606001604052806000815260200160008152602001600081525090565b81526020016148266148ce565b81526020016148336148a6565b8152602001614840614904565b815260200161484d6148a6565b815260200161485a61475f565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b03811182821017156149665761496661492e565b60405290565b604051608081016001600160401b03811182821017156149665761496661492e565b60405161018081016001600160401b03811182821017156149665761496661492e565b60405161010081016001600160401b03811182821017156149665761496661492e565b604051606081016001600160401b03811182821017156149665761496661492e565b60405161014081016001600160401b03811182821017156149665761496661492e565b604051601f8201601f191681016001600160401b0381118282101715614a4157614a4161492e565b604052919050565b6001600160a01b0381168114614a5e57600080fd5b50565b8035613f9c81614a49565b600060e08284031215614a7e57600080fd5b614a86614944565b90508135614a9381614a49565b81526020820135614aa381614a49565b60208201526040820135614ab681614a49565b60408201526060820135614ac981614a49565b6060820152614ada60808301614a61565b6080820152614aeb60a08301614a61565b60a0820152614afc60c08301614a61565b60c082015292915050565b600060808284031215614b1957600080fd5b614b2161496c565b90508135614b2e81614a49565b81526020820135614b3e81614a49565b60208201526040820135614b5181614a49565b60408201526060820135614b6481614a49565b606082015292915050565b60006001600160401b03821115614b8857614b8861492e565b5060051b60200190565b600082601f830112614ba357600080fd5b8135614bb6614bb182614b6f565b614a19565b8082825260208201915060208360051b860101925085831115614bd857600080fd5b602085015b83811015614bfe578035614bf081614a49565b835260209283019201614bdd565b5095945050505050565b803560098110613f9c57600080fd5b803560038110613f9c57600080fd5b60006101808284031215614c3957600080fd5b614c4161498e565b9050614c4c82614c08565b8152614c5a60208301614c17565b602082015260408281013590820152606080830135908201526080808301359082015260a0808301359082015260c0808301359082015260e080830135908201526101008083013590820152610120808301359082015261014080830135908201526101609182013591810191909152919050565b80358015158114613f9c57600080fd5b600060808284031215614cf157600080fd5b614cf961496c565b9050614d0482614ccf565b8152614d1260208301614ccf565b6020820152614d2360408301614ccf565b6040820152614b6460608301614ccf565b600082601f830112614d4557600080fd5b8135614d53614bb182614b6f565b8082825260208201915060208360051b860101925085831115614d7557600080fd5b602085015b83811015614bfe578035835260209283019201614d7a565b60006102408284031215614da557600080fd5b614dad61496c565b905081356001600160401b03811115614dc557600080fd5b82016101008185031215614dd857600080fd5b614de06149b1565b614de982614a61565b8152614df760208301614a61565b6020820152614e0860408301614a61565b6040820152614e1960608301614a61565b6060820152614e2a60808301614a61565b6080820152614e3b60a08301614a61565b60a0820152614e4c60c08301614a61565b60c082015260e08201356001600160401b03811115614e6a57600080fd5b614e7686828501614b92565b60e083015250825250614e8c8360208401614c26565b6020820152614e9f836101a08401614cdf565b60408201526102208201356001600160401b03811115614ebe57600080fd5b614eca84828501614d34565b60608301525092915050565b600060208284031215614ee857600080fd5b604051602081016001600160401b0381118282101715614f0a57614f0a61492e565b604052905080614f1983614ccf565b905292915050565b60008183036101c0811215614f3557600080fd5b614f3d6149d4565b91506060811215614f4d57600080fd5b614f556149d4565b8335614f6081614a49565b81526020840135614f7081614a49565b60208201526040840135614f8381614a49565b60408201528252610140605f1982011215614f9d57600080fd5b50614fa66149f6565b606083810135825260808085013560208085019190915260a080870135604086015260c0808801359486019490945260e0808801359386019390935261010080880135918601919091526101208088013594860194909452610140870135928501929092526101608601359184019190915261018085013591830191909152820152615036836101a08401614ed6565b604082015292915050565b803560028110613f9c57600080fd5b60006103a0828403121561506357600080fd5b61506b614944565b90506150778383614a6c565b81526150868360e08401614b07565b60208201526101608201356001600160401b038111156150a557600080fd5b6150b184828501614d92565b60408301525061018082013560608201526150d0836101a08401614f21565b608082015261036082013560a0820152614afc6103808301615041565b6000604082840312156150ff57600080fd5b604080519081016001600160401b03811182821017156151215761512161492e565b604052823581526020928301359281019290925250919050565b600060c0828403121561514d57600080fd5b6151556149d4565b905061516183836150ed565b815261517083604084016150ed565b602082015261503683608084016150ed565b60008060e0838503121561519557600080fd5b82356001600160401b038111156151ab57600080fd5b6151b785828601615050565b9250506151c7846020850161513b565b90509250929050565b60008060008061018085870312156151e757600080fd5b84356151f281614a49565b9350602085013561520281614a49565b92506152118660408701614b07565b91506152208660c0870161513b565b905092959194509250565b6000806060838503121561523e57600080fd5b82356001600160401b0381111561525457600080fd5b61526085828601615050565b9250506151c784602085016150ed565b6000806000806000806000610380888a03121561528c57600080fd5b873561529781614a49565b965060208801356152a781614a49565b95506152b68960408a01614f21565b94506152c6896102008a01614b07565b93506152d6896102808a0161513b565b92506152e56103408901614ccf565b91506152f46103608901614ccf565b905092959891949750929550565b6000815180845260005b818110156153285760208185018101518683018201520161530c565b506000602082860101526020601f19601f83011685010191505092915050565b831515815260a06020820152600061536360a0830185615302565b9050825160408301526020830151606083015260408301516080830152949350505050565b6000806000806000808688036102208112156153a357600080fd5b87356153ae81614a49565b96506153bd8960208a01614b07565b95506153cc8960a08a0161513b565b94506101608801356153dd81614a49565b93506153ec6101808901614ccf565b9250608061019f198201121561540157600080fd5b5061540a61496c565b6101a088013581526101c088013560208201526101e088013560408201526102009097013560608801525093969295509093909291565b6000806000806000610340868803121561545a57600080fd5b853561546581614a49565b94506154748760208801614b07565b93506154838760a0880161513b565b9250615493876101608801614f21565b94979396509194610320013592915050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000826154e0576154e06154a5565b600160ff1b8214600019841416156154fa576154fa6154bb565b500590565b60008261550e5761550e6154a5565b500490565b8082018281126000831280158216821582161715615533576155336154bb565b505092915050565b818103600083128015838313168383128216171561555b5761555b6154bb565b5092915050565b918252602082015260400190565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b6155b882825180518252602090810151910152565b602081810151805160408501529081015160608401525060400151805160808301526020015160a090910152565b6001600160a01b03858116825284166020820152610180810161560c6040830185615570565b611bc360c08301846155a3565b6001600160a01b038681168252851660208201526101a0810161563f6040830186615570565b61564c60c08301856155a3565b8215156101808301529695505050505050565b6000600160ff1b8201615674576156746154bb565b5060000390565b808202811582820484141761121a5761121a6154bb565b80820260008212600160ff1b841416156156ae576156ae6154bb565b818105831482151761121a5761121a6154bb565b6000602082840312156156d457600080fd5b5051919050565b6001600160a01b0392831681529116602082015260400190565b6080815260006157086080830187615302565b6020830195909552506040810192909252606090910152919050565b8082018082111561121a5761121a6154bb565b8181038181111561121a5761121a6154bb565b6001600160a01b0391909116815260200190565b60006020828403121561577057600080fd5b815161174781614a49565b6000806040838503121561578e57600080fd5b505080516020909101519092909150565b634e487b7160e01b600052602160045260246000fdfea26469706673582212207f204beb2d6e38f6e795afd435d4b32d914677c62ac22f06171bf326cf87ec7164736f6c634300081d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100775760003560e01c8063610e3cb91461007c5780637396d38c146100be57806381db61b8146100e0578063a6dcd97614610110578063d7e3321114610132578063dac6485714610145578063e22de7931461016f575b600080fd5b61008f61008a366004615182565b61019d565b6040805195865260208601949094529284019190915260608301521515608082015260a0015b60405180910390f35b8180156100ca57600080fd5b506100de6100d93660046151d0565b61045a565b005b6100f36100ee36600461522b565b6105ad565b6040805193845260208401929092521515908201526060016100b5565b61012361011e366004615270565b6106f5565b6040516100b593929190615348565b6100de610140366004615270565b610bbf565b610158610153366004615388565b610dd7565b6040805192151583526020830191909152016100b5565b61018261017d366004615441565b610ea3565b604080519384526020840192909252908201526060016100b5565b60008060008060006101b88760400151602001516040015190565b6000036101f05760008060006101df6101d78b60800151604001515190565b8a5190611203565b600094509450945094509450610450565b6102246040518060a00160405280600081526020016000815260200160008152602001600015158152602001600081525090565b604080516080810182528951516001600160a01b031681526020808b0151818301528a83015101518201516102829282019061026490611220565b611220565b81526020016102798b60400151604001515190565b1515905261128e565b1515606083015280825288515160208a01515160408b01516102b393906102ae90602001516040015190565b61134c565b808252600012156102e3578651602001516102cd90611220565b81516102d991906154d1565b60208201526102f8565b80518751516102f29190611398565b60208201525b608088015160400151511561033557865160200151604089015161032190602001516040015190565b61032b91906154ff565b6040820152610359565b61035361034b8960400151602001516040015190565b88515161140c565b60408201525b600061036b8960800151604001515190565b156103935781602001516103828360400151611220565b61038c9190615513565b90506103b2565b81602001516103a58360400151611220565b6103af919061553b565b90505b60008112156103ed57815160408a8101516020015101516040516378320e4960e11b81526004016103e4929190615562565b60405180910390fd5b6104286104038a60400151602001516040015190565b61040c8361142f565b60408c01516020015160a0015160808d01516040015151611481565b6080830181905282516020840151604085015160609095015191995097509295509350909150505b9295509295909350565b60405163034aadf760e61b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__9063d2ab7dc0906104979087908790879087906004016155e6565b60006040518083038186803b1580156104af57600080fd5b505af41580156104c3573d6000803e3d6000fd5b5050604051631450a87960e01b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__9250631450a8799150610507908790879087908790600190600401615619565b60006040518083038186803b15801561051f57600080fd5b505af4158015610533573d6000803e3d6000fd5b5050604051631450a87960e01b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__9250631450a8799150610577908790879087908790600090600401615619565b60006040518083038186803b15801561058f57600080fd5b505af41580156105a3573d6000803e3d6000fd5b5050505050505050565b6000806000806105c68660400151602001516040015190565b9050806000036105fb5760006105ed6105e58860800151604001515190565b879015611203565b6000935093509350506106ee565b610621604051806060016040528060008152602001600015158152602001600081525090565b604080516080810182528851516001600160a01b031681526020808a01519082015261067091810161065285611220565b61065b9061565f565b81526020016102798a60400151604001515190565b1515602080840191909152818352885151908901515160408a015161069f93906102ae90602001516040015190565b80825260808801516020808201518051908201516040808d01519093015160a001519290930151516106d6948b94929388926114fc565b60408201819052815160209092015191955093509150505b9250925092565b600060606107016146f9565b61070961471a565b6107116146f9565b6107248c8a8a8d61017d8f602001515190565b5050825261073e6107378b516040015190565b8a8a6116ad565b60408301819052516107558b602001516040015190565b61075f919061567b565b606083015261077361025f8b602001515190565b61077c9061565f565b8260800181815250506107be60405180608001604052808e6001600160a01b031681526020018b8152602001846080015181526020016102798d604001515190565b151560c084015260a08301819052895160208c0151516107e0928f929161134c565b60a083015260006107f68b602001516060015190565b136108225787516020015161080a90611220565b60208b01516060015161081d9190615692565b610841565b87515161082e90611220565b60208b0151606001516108419190615692565b8260a0018181516108529190615513565b90525060a082015160001361086d57600060a08301526108bb565b600061087d8d8b6000015161174e565b9050600061089961025f6108938e602001515190565b846117c7565b6108a29061565f565b9050808460a0015112156108b85760a084018190525b50505b60006040518061014001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c8152602001846040015181526020018460c00151151581526020018b604001516001600160a01b031681526020018b606001516001600160a01b031681526020016109358d602001515190565b81526000602082018190526040909101819052909150610954826117e0565b90506000846040015160000151826101e00151610971919061567b565b905061097c81611220565b60a08601518651606088015161099190611220565b61099b9190615513565b6109a59190615513565b6109af919061553b565b845288156109cf576109c58f8d60000151611a4f565b60208601526109e3565b6109dd8f8d60000151611a69565b60208601525b6109ff61025f6109f58f602001515190565b87602001516117c7565b60408501528915610b0e57610ac78f6001600160a01b031663bd02d0f5604051602001610a529060208082526012908201527113525397d0d3d31310551154905317d554d160721b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610a8691815260200190565b602060405180830381865afa158015610aa3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025f91906156c2565b6020850181905284511215610b0e57505060408051808201909152600e81526d1b5a5b8818dbdb1b185d195c985b60921b6020820152600196509450909250610bb2915050565b8351600012610b4457505060408051808201909152600381526203c20360ec1b6020820152600196509450909250610bb2915050565b604084015184511215610b9657505060408051808201909152601b81527a6d696e20636f6c6c61746572616c20666f72206c6576657261676560281b6020820152600196509450909250610bb2915050565b5050604080516020810190915260008082529650945090925050505b9750975097945050505050565b6020850151511580610bd657506020808601510151155b15610c0157602085810151805191015160405163bff65b3f60e01b81526103e4929190600401615562565b8351604051630ef68b4760e11b815273__$e53db83827f4e07ebc418caf7145b8c2d5$__91631ded168e91610c3a918b916004016156db565b60006040518083038186803b158015610c5257600080fd5b505af4158015610c66573d6000803e3d6000fd5b50505050610c7f84610c7a87516040015190565b611a83565b8115610d7d576000876001600160a01b031663bd02d0f5604051602001610ccf9060208082526015908201527413525397d413d4d2551253d397d4d2569157d554d1605a1b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610d0391815260200190565b602060405180830381865afa158015610d20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4491906156c2565b905080610d5387602001515190565b1015610d7b57602086015151816040516342f7d98d60e11b81526004016103e4929190615562565b505b6000806000610d928a8a8a8a8a8960006106f5565b9250925092508215610dcb5781816000015182602001518360400151604051631782422160e31b81526004016103e494939291906156f5565b50505050505050505050565b6000806000610de78689896116ad565b90506000610df88260000151611220565b610e058660200151611220565b610e0f9190615692565b9050600085604001511215610e30576040850151610e2d9082615513565b90505b6000811215610e4657600093509150610e989050565b6000610e588b8b88606001518a611ab3565b90506000610e6a8c8c60000151611a69565b905081811115610e78578091505b6000610e8b61025f8960000151856117c7565b8412159650929450505050505b965096945050505050565b6000806000610f1560405180610180016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610f30610f2688604001515190565b8951906000611aec565b9050610f4f81610f4589602090810151015190565b61025f919061567b565b8252604087015151610f7b578151610f6c61025f89602001515190565b610f76919061553b565b610f96565b610f8a61025f88602001515190565b8251610f96919061553b565b60208301819052604083018190526000121561111557604087015151610fc0578860600151610fc6565b88604001515b6001600160a01b031660608301819052610fe3908b908b90611b25565b6080830152604087015151610ffd57604088015151611004565b6020880151515b60a08301819052608083015161101a919061567b565b60c0830152875161103c908b908b906110358b604001515190565b6001611bcc565b60e083015288516040880151516110b2918c918560e001518660c00151604051602001611097906020808252601a90820152794d41585f504e4c5f464143544f525f464f525f5452414445525360301b604082015260600190565b60405160208183030381529060405280519060200120611c58565b610100830181905260e0830151148015906110d257506000826101000151135b80156110e2575060008260e00151135b156111155761110f6110f7836020015161142f565b83610100015161110a8560e0015161142f565b611ca8565b60208301525b8561112288602001515190565b0361113b5760208088015101515b610120830152611195565b6040870151511561116e576111308661115989602090810151015190565b611163919061567b565b60208901515161140c565b602087810151805191015161118490889061567b565b61118e91906154ff565b6101208301525b6111b782602001518361012001516111b28a602090810151015190565b611ce8565b61014083015260408201516101208301516020808a015101516111db929190611ce8565b610160830181905261014083015161012090930151929b909a50919850909650505050505050565b600081611211578251611217565b82602001515b90505b92915050565b60006001600160ff1b0382111561128a5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016103e4565b5090565b600080600061129c84611cf5565b90506000806112b8866000015187602001516000015185611d38565b91509150600082126112cf57909590945092505050565b6000806112e88860000151896020015160200151611e62565b91509150816112fe575091969095509350505050565b600061130a8983611f78565b90506000806113268b600001518c602001516000015185611d38565b9150915086821261133857868661133b565b81815b995099505050505050505050915091565b60008083121561135d575081611390565b600061136b86866001611ff2565b9050600061137c61025f85846117c7565b90508085131561138a578094505b84925050505b949350505050565b6000808312156113da576113ab82611220565b6113b483611220565b6113be908561553b565b6113c9906001615513565b6113d391906154d1565b905061121a565b6113e382611220565b60016113ee84611220565b6113f89086615513565b611402919061553b565b61121791906154d1565b600081600161141b8286615724565b6114259190615737565b61121791906154ff565b60008082121561128a5760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016103e4565b6000836000036114a457604051633df4253160e01b815260040160405180910390fd5b60006114b085876154ff565b90508280156114bf5750838111155b806114d35750821580156114d35750838110155b156114df579050611390565b808460405163e09ad0e960e01b81526004016103e4929190615562565b600061152260405180606001604052806000815260200160008152602001600081525090565b61152d898415611203565b808252602082015285158015906115445750600087115b15611648578261155c576115578561565f565b61155e565b845b60408201819052600013801561158857508561158682604001516115819061565f565b61142f565b115b156115ae578060400151866040516378320e4960e11b81526004016103e4929190615562565b60006115b987611220565b6115c88a84604001518b611ca8565b6115d291906154d1565b90506000816115e48460000151611220565b6115ee9190615513565b90506000811215611637578251604080850151905163cc32db9960e01b8152600481018490526024810192909252604482018c905260648201526084810189905260a4016103e4565b6116408161142f565b602084015250505b828015611659575083816020015110155b80611671575082158015611671575083816020015111155b15611681576020015190506116a2565b80602001518460405163e09ad0e960e01b81526004016103e4929190615562565b979650505050505050565b6116b561475f565b82604001516001600160a01b0316846001600160a01b0316036116dd57506020810151611747565b82606001516001600160a01b0316846001600160a01b03160361170557506040810151611747565b82602001516001600160a01b0316846001600160a01b03160361172a57508051611747565b8251604051635f2394d160e11b81526103e49186916004016156db565b9392505050565b6000826001600160a01b031663bd02d0f561176884612019565b6040518263ffffffff1660e01b815260040161178691815260200190565b602060405180830381865afa1580156117a3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121791906156c2565b6000611217838368327cb2734119d3b7a9601e1b6120bb565b6117e8614779565b6000611822836000015184602001518560600151866080015161180e8860400151515190565b604089015151602001518960e001516120c8565b9050600061183884600001518560400151612552565b905061184d84600001518560600151836125df565b6060830152610120840151156118835783516040850151516020015161187d91908660e0015187606001516126ee565b60a08301525b8160a00151606001518260a00151602001518360600151606001518460600151602001518561018001516118b79190615724565b6118c19190615737565b6118cb9190615724565b6118d59190615737565b61016083015260a082015160609081015181840151909101516118f89190615724565b826101400181815161190a9190615724565b9052508351604080860151805160208101519083015191909201515161193293929190612894565b604080840151606001919091528451908501515160200151611962919060a087015160408089015101515161290f565b604080840151608001919091528451908501515160200151611992919060c087015160408089015101515161290f565b826040015160a00181815250506119b18260400151856040015161292b565b60408301528351606085015160e08601516101008701516119d4939291906129a7565b82608001819052508161020001518260800151604001518360a0015160200151846060015160200151856101a00151611a0d9190615724565b611a179190615724565b611a219190615724565b611a2b9190615737565b6101c08301819052604083015151611a4291615724565b6101e08301525092915050565b6000826001600160a01b031663bd02d0f561176884612a0f565b6000826001600160a01b031663bd02d0f561176884612a60565b611a8d8282612a9b565b611aaf5781516040516341ce349f60e11b81526103e4919083906004016156db565b5050565b600080611ac1868685612ad4565b9050611acd8185612b27565b90506000611ae087876000015186612b57565b90506116a282826117c7565b60008215611b0d5781611b00578351611b06565b83602001515b9050611747565b81611b1c578360200151611390565b50509051919050565b600080611b3a84604001518560600151612bd1565b905080856001600160a01b031663bd02d0f5611b5a876000015187612c00565b6040518263ffffffff1660e01b8152600401611b7891815260200190565b602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906156c2565b611bc391906154ff565b95945050505050565b600080611bdd61025f888887612ad4565b90506000611bec888887612c88565b9050811580611bf9575080155b15611c0957600092505050611bc3565b6000611c16878787611aec565b90506000611c2761025f838561567b565b9050600087611c3f57611c3a828661553b565b611c49565b611c49858361553b565b9b9a5050505050505050505050565b600080841215611c69575082611c9e565b6000611c7788848989612ccf565b90506000611c8861025f86846117c7565b9050808613611c975785611c99565b805b925050505b9695505050505050565b600080611cbe85611cb886612ceb565b856120bb565b905060008413611cdf57611cd181611220565b611cda9061565f565b611bc3565b611bc381611220565b6000611390838584611ca8565b611cfd6148a6565b6000611d13836000015184602001516001612ad4565b90506000611d2b846000015185602001516000612ad4565b9050611390848383612cfc565b6000806000611d4f84600001518560200151612dee565b90506000611d6585604001518660600151612dee565b6060860151604087015160208801518851939450909211159111151460006001600160a01b03891663bd02d0f5611d9b8a612e10565b6040518263ffffffff1660e01b8152600401611db991815260200190565b602060405180830381865afa158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa91906156c2565b90508383108215611e30576000611e128b8b84612e53565b9050611e2086868386612e62565b8297509750505050505050611e5a565b600080611e3d8c8c612ea0565b91509150611e4e8787848488612fb4565b98509196505050505050505b935093915050565b6000806000846001600160a01b031663a6ed563e611e7f86612ffd565b6040518263ffffffff1660e01b8152600401611e9d91815260200190565b602060405180830381865afa158015611eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ede91906156c2565b905080611ef2576000809250925050611f71565b6001856001600160a01b031663dc97d962611f0c84613033565b6040518263ffffffff1660e01b8152600401611f2a91815260200190565b602060405180830381865afa158015611f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6b91906156c2565b92509250505b9250929050565b611f806148a6565b6000806000841315611f9c57611f958461142f565b9050611fab565b611fa86115818561565f565b91505b600085604001511215611fe7576000611fcb86604001516115819061565f565b9050611fd78184615724565b9250611fe38183615724565b9150505b611bc3858383612cfc565b6000806000612001868661309e565b91509150836120105780611c9e565b50949350505050565b6000604051602001612070906020808252602b908201527f4d41585f504f534954494f4e5f494d504143545f464143544f525f464f525f4c60408201526a49515549444154494f4e5360a81b606082015260800190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038416908201526060015b604051602081830303815290604052805190602001209050919050565b600061139084848461313a565b6120d0614779565b6120d8614779565b60c0810187905280516001600160a01b03861660409091015260006120fe8a8a88613224565b865160c081019290925260808201929092526001600160a01b039283166020820152929092529091508a1663bd02d0f5612138878a613563565b6040518263ffffffff1660e01b815260040161215691815260200190565b602060405180830381865afa158015612173573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219791906156c2565b60e083018190528851906121ac9086906117c7565b6121b691906154ff565b6101a08301526001600160a01b038a1663bd02d0f56121d4886135d6565b6040518263ffffffff1660e01b81526004016121f291815260200190565b602060405180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223391906156c2565b602083018051919091525151156122fa57896001600160a01b031663bd02d0f561226484602001516000015161360b565b6040518263ffffffff1660e01b815260040161228291815260200190565b602060405180830381865afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c391906156c2565b6020808401805182019290925290510151156122fa576122f0826101a001518360200151602001516117c7565b6020830151604001525b815151156123f057815160808082015160a090920191909152825160c08101519101516123279190615724565b825160600152815160c00151602080840151015111156123925781516060015160208084015101511161237157602080830151015182516060015161236c9190615737565b612373565b805b825160a0908101919091528251015181111561239257815160a0018190525b6123a9826101a00151836000015160a001516117c7565b825161012001526101a0820151825160c001516123c691906117c7565b825161010090810191909152825190810151610120909101516123e99190615724565b825160e001525b8151610100015160208301516040015111612411578151610100015161241b565b8160200151604001515b6102008301819052825161012001516101a084015161243a9190615737565b6124449190615737565b6101008301526040516001600160a01b038b169063bd02d0f59061249b906020016020808252601c908201527b2827a9a4aa24a7a72fa322a2afa922a1a2a4ab22a92fa320a1aa27a960211b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016124cf91815260200190565b602060405180830381865afa1580156124ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251091906156c2565b6101208301819052610100830151612527916117c7565b610140830181905261010083015161253f9190615737565b6101808301525098975050505050505050565b6000806125708461256585516020015190565b604086015151613644565b90508061258284602001516080015190565b11156125ad5760208301516080015181604051634cd96ac160e11b81526004016103e4929190615562565b60006125be84602001516080015190565b6125c89083615737565b9050611bc36125d985602001515190565b826117c7565b6125e76148a6565b6125ef6148a6565b82815283516125fe90846154ff565b816020018181525050846001600160a01b031663bd02d0f5604051602001612657906020808252601d908201527f424f52524f57494e475f4645455f52454345495645525f464143544f52000000604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161268b91815260200190565b602060405180830381865afa1580156126a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126cc91906156c2565b6040820181905260208201516126e1916117c7565b6060820152949350505050565b6126f66148a6565b6126fe6148a6565b6000866001600160a01b031663bd02d0f56127188861365f565b6040518263ffffffff1660e01b815260040161273691815260200190565b602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277791906156c2565b90508060000361278957509050611390565b61279385826117c7565b80835284516127a2919061140c565b826020018181525050866001600160a01b031663bd02d0f56040516020016127fb906020808252601f908201527f4c49515549444154494f4e5f4645455f52454345495645525f464143544f5200604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161282f91815260200190565b602060405180830381865afa15801561284c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287091906156c2565b604083018190526020830151612885916117c7565b60608301525095945050505050565b6000846001600160a01b031663bd02d0f56128b086868661369b565b6040518263ffffffff1660e01b81526004016128ce91815260200190565b602060405180830381865afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc391906156c2565b6000846001600160a01b031663bd02d0f56128b086868661373c565b6129336148ce565b612957836060015161294a846020015160a0015190565b6020850151516001613789565b8352608083015161297e90612971846020015160c0015190565b6020850151516000613789565b602084015260a083015161299b90612971846020015160e0015190565b60408401525090919050565b6129af614904565b6129b7614904565b6001600160a01b0383166129cc579050611390565b6001600160a01b03831681526129e286846137c0565b602082018190528551906129f79086906117c7565b612a0191906154ff565b604082015295945050505050565b60006040516020016120709060208082526025908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4c495155494460408201526420aa24a7a760d91b606082015260800190565b60006040516020016120709060208082526015908201527426a4a72fa1a7a62620aa22a920a62fa320a1aa27a960591b604082015260600190565b600082604001516001600160a01b0316826001600160a01b031614806112175750506060909101516001600160a01b0391821691161490565b600080612ae984604001518560600151612bd1565b90506000612b0286866000015187604001518786613906565b90506000612b1b87876000015188606001518887613906565b90506116a28183615724565b600080821315612b4457612b3a82612ceb565b6113d39084615724565b612b4d82612ceb565b6112179084615737565b6000836001600160a01b031663bd02d0f5612b72858561398c565b6040518263ffffffff1660e01b8152600401612b9091815260200190565b602060405180830381865afa158015612bad573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139091906156c2565b6000816001600160a01b0316836001600160a01b031614612bf3576001612bf6565b60025b60ff169392505050565b6000604051602001612c31906020808252600b908201526a1413d3d317d05353d5539560aa1b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b0380861691830191909152831660608201526080015b60405160208183030381529060405280519060200120905092915050565b600080612c9d84604001518560600151612bd1565b90506000612cb6868660000151876040015187866139ea565b90506000612b1b878760000151886060015188876139ea565b6000846001600160a01b031663bd02d0f56128b0868686613a07565b60008082121561128a575060000390565b612d046148a6565b60608401518390839015612d705760008660400151128015612d35575084612d3387604001516115819061565f565b115b15612d5b5785604001518560405163756d7c9d60e11b81526004016103e4929190615562565b612d69858760400151612b27565b9150612dca565b60008660400151128015612d93575083612d9187604001516115819061565f565b115b15612db95785604001518460405163022bc34560e61b81526004016103e4929190615562565b612dc7848760400151612b27565b90505b60408051608081018252958652602086019490945292840152506060820152919050565b6000818311612e0657612e018383615737565b611217565b6112178284615737565b6000604051602001612070906020808252601f908201527f504f534954494f4e5f494d504143545f4558504f4e454e545f464143544f5200604082015260600190565b60008060006120018686612ea0565b600084841081612e86612e76888787613a7b565b612e81888888613a7b565b612dee565b90506000612e948284613a94565b98975050505050505050565b6000806000846001600160a01b031663bd02d0f5612ebf866001613ab7565b6040518263ffffffff1660e01b8152600401612edd91815260200190565b602060405180830381865afa158015612efa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1e91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613ab7565b6040518263ffffffff1660e01b8152600401612f5a91815260200190565b602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906156c2565b905080821115612fa9578091505b909590945092505050565b600080612fc2878685613a7b565b90506000612fd1878686613a7b565b90506000612fdf8383612dee565b90506000612fef82848611613a94565b9a9950505050505050505050565b60006040516020016120709060208082526010908201526f1592549515505317d513d2d15397d25160821b604082015260600190565b6000604051602001613076906020808252601f908201527f5649525455414c5f494e56454e544f52595f464f525f504f534954494f4e5300604082015260600190565b604051602081830303815290604052805190602001208260405160200161209e929190615562565b6000806000846001600160a01b031663bd02d0f56130bd866001613af3565b6040518263ffffffff1660e01b81526004016130db91815260200190565b602060405180830381865afa1580156130f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061311c91906156c2565b90506000856001600160a01b031663bd02d0f5612f3c876000613af3565b60008080600019858709858702925082811083820303915050806000036131745783828161316a5761316a6154a5565b0492505050611747565b8084116131bb5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016103e4565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000808080806001600160a01b03871661324c57506000935083925082915081905080613558565b6040516310ae4b6b60e31b81526000906001600160a01b038916906385725b589061327b908a9060040161574a565b602060405180830381865afa158015613298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132bc91906156c2565b90506000808080841561350a576040516306459e2360e51b8152600481018690526001600160a01b038d169063c8b3c46090602401602060405180830381865afa15801561330e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613332919061575e565b935060008c6001600160a01b0316631582a018866040518263ffffffff1660e01b8152600401613362919061574a565b602060405180830381865afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a391906156c2565b60405163039af9eb60e01b8152600481018290529091506001600160a01b038e169063039af9eb906024016040805180830381865afa1580156133ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061340e919061577b565b90945092506001600160a01b038e1663bd02d0f561342b83613b33565b6040518263ffffffff1660e01b815260040161344991815260200190565b602060405180830381865afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a91906156c2565b915060008d6001600160a01b03166371a6a790876040518263ffffffff1660e01b81526004016134ba919061574a565b602060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb91906156c2565b90508015613507578093505b50505b600061352b61271061351c858761567b565b61352691906154ff565b613b74565b9050600061353885613b74565b905060006135468383615737565b979c50959a5095985096509450505050505b939792965093509350565b600060405160200161359c906020808252601390820152722827a9a4aa24a7a72fa322a2afa320a1aa27a960691b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038516908201528215156060820152608001612c6a565b6000604051602001612070906020808252600f908201526e282927afaa2920a222a92faa24a2a960891b604082015260600190565b600060405160200161307690602080825260139082015272282927afa224a9a1a7aaa72a2fa320a1aa27a960691b604082015260600190565b6000836001600160a01b031663bd02d0f5612b728585613b99565b6000604051602001612070906020808252601690820152752624a8aaa4a220aa24a7a72fa322a2afa320a1aa27a960511b604082015260600190565b60006040516020016136dc906020808252601b908201527a46554e44494e475f4645455f414d4f554e545f5045525f53495a4560281b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b038087169183019190915284166060820152821515608082015260a0015b6040516020818303038152906040528051906020012090509392505050565b60006040516020016136dc9060208082526021908201527f434c41494d41424c455f46554e44494e475f414d4f554e545f5045525f53495a6040820152604560f81b606082015260800190565b6000806137968587615737565b9050611c9e84826137ba66038d7ea4c6800068327cb2734119d3b7a9601e1b61567b565b86613bda565b600080836001600160a01b031663bd02d0f56040516020016138079060208082526011908201527026a0ac2faaa4afa322a2afa320a1aa27a960791b604082015260600190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161383b91815260200190565b602060405180830381865afa158015613858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387c91906156c2565b90506000846001600160a01b031663bd02d0f561389886613c01565b6040518263ffffffff1660e01b81526004016138b691815260200190565b602060405180830381865afa1580156138d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f791906156c2565b90508181106113905781611bc3565b600081866001600160a01b031663bd02d0f5613923888888613c34565b6040518263ffffffff1660e01b815260040161394191815260200190565b602060405180830381865afa15801561395e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398291906156c2565b611c9e91906154ff565b600060405160200161359c9060208082526032908201527f4d494e5f434f4c4c41544552414c5f464143544f525f464f525f4f50454e5f49604082015271272a22a922a9aa2fa6aaa62a24a82624a2a960711b606082015260800190565b600081866001600160a01b031663bd02d0f5613923888888613c67565b6000604051602001613a3b906020808252600e908201526d26a0ac2fa827262fa320a1aa27a960911b604082015260600190565b60408051601f1981840301815282825280516020918201209083015281018590526001600160a01b0384166060820152821515608082015260a00161371d565b600080613a888584613ca4565b9050611bc381856117c7565b60008115613aa5576113d383611220565b613aae83611220565b6113d39061565f565b600060405160200161359c906020808252601690820152752827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960511b604082015260600190565b600060405160200161359c906020808252601a908201527926a0ac2fa827a9a4aa24a7a72fa4a6a820a1aa2fa320a1aa27a960311b604082015260600190565b6000604051602001613076906020808252601b908201527a26a4a72fa0a32324a624a0aa22afa922aba0a9222fa320a1aa27a960291b604082015260600190565b6000612710613b8f68327cb2734119d3b7a9601e1b8461567b565b61121a91906154ff565b600060405160200161359c906020808252601b908201527a21aaa6aaa620aa24ab22afa127a92927aba4a723afa320a1aa27a960291b604082015260600190565b60008115613bf657613bef8585856001613d03565b9050611390565b611bc385858561313a565b6000604051602001612070906020808252600d908201526c2aa4afa322a2afa320a1aa27a960991b604082015260600190565b60006040516020016136dc906020808252600d908201526c13d4115397d2539511549154d5609a1b604082015260600190565b60006040516020016136dc906020808252601790820152764f50454e5f494e5445524553545f494e5f544f4b454e5360481b604082015260600190565b600068327cb2734119d3b7a9601e1b831015613cc25750600061121a565b68327cb2734119d3b7a9601e1b8203613cdc57508161121a565b6000613cf8613cea85613d54565b613cf385613d54565b613d65565b905061139081613da5565b600080613d1186868661313a565b90506001836002811115613d2757613d2761579f565b148015613d44575060008480613d3f57613d3f6154a5565b868809115b15611bc357611c9e600182615724565b600061121a64e8d4a51000836154ff565b600082600003613d8b578115613d7c5760006113d3565b50670de0b6b3a764000061121a565b611217613da0613d9a85613db6565b84613e6c565b613e78565b600061121a64e8d4a510008361567b565b6000670de0b6b3a7640000821015613de457604051633621413760e21b8152600481018390526024016103e4565b6000613df9670de0b6b3a76400008404613ebe565b670de0b6b3a764000081029250905082811c670de0b6b3a763ffff198101613e22575050919050565b6706f05b59d3b200005b8015613e6457670de0b6b3a7640000828002049150671bc16d674ec800008210613e5c579283019260019190911c905b60011c613e2c565b505050919050565b60006112178383613fa1565b6000680a688906bd8b0000008210613ea657604051634a4f26f160e01b8152600481018390526024016103e4565b670de0b6b3a7640000604083901b0461174781614067565b6000600160801b8210613ede57608091821c91613edb9082615724565b90505b600160401b8210613efc57604091821c91613ef99082615724565b90505b600160201b8210613f1a57602091821c91613f179082615724565b90505b620100008210613f3757601091821c91613f349082615724565b90505b6101008210613f5357600891821c91613f509082615724565b90505b60108210613f6e57600491821c91613f6b9082615724565b90505b60048210613f8957600291821c91613f869082615724565b90505b60028210613f9c5761121a600182615724565b919050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110613fe55760405163698d9a0160e11b8152600481018290526024016103e4565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff82119050826000036140235780670de0b6b3a764000085040194505050505061121a565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b600160bf1b6001603f1b8216156140875768016a09e667f3bcc9090260401c5b6001603e1b8216156140a2576801306fe0a31b7152df0260401c5b6001603d1b8216156140bd576801172b83c7d517adce0260401c5b6001603c1b8216156140d85768010b5586cf9890f62a0260401c5b6001603b1b8216156140f3576801059b0d31585743ae0260401c5b6001603a1b82161561410e57680102c9a3e778060ee70260401c5b600160391b8216156141295768010163da9fb33356d80260401c5b600160381b82161561414457680100b1afa5abcbed610260401c5b600160371b82161561415f5768010058c86da1c09ea20260401c5b600160361b82161561417a576801002c605e2e8cec500260401c5b600160351b82161561419557680100162f3904051fa10260401c5b600160341b8216156141b0576801000b175effdc76ba0260401c5b600160331b8216156141cb57680100058ba01fb9f96d0260401c5b600160321b8216156141e65768010002c5cc37da94920260401c5b600160311b821615614201576801000162e525ee05470260401c5b600160301b82161561421c5768010000b17255775c040260401c5b6001602f1b821615614237576801000058b91b5bc9ae0260401c5b6001602e1b82161561425257680100002c5c89d5ec6d0260401c5b6001602d1b82161561426d5768010000162e43f4f8310260401c5b6001602c1b82161561428857680100000b1721bcfc9a0260401c5b6001602b1b8216156142a35768010000058b90cf1e6e0260401c5b6001602a1b8216156142be576801000002c5c863b73f0260401c5b600160291b8216156142d957680100000162e430e5a20260401c5b600160281b8216156142f4576801000000b1721835510260401c5b600160271b82161561430f57680100000058b90c0b490260401c5b600160261b82161561432a5768010000002c5c8601cc0260401c5b600160251b821615614345576801000000162e42fff00260401c5b600160241b8216156143605768010000000b17217fbb0260401c5b600160231b82161561437b576801000000058b90bfce0260401c5b600160221b82161561439657680100000002c5c85fe30260401c5b600160211b8216156143b15768010000000162e42ff10260401c5b600160201b8216156143cc57680100000000b17217f80260401c5b63800000008216156143e75768010000000058b90bfc0260401c5b6340000000821615614402576801000000002c5c85fe0260401c5b632000000082161561441d57680100000000162e42ff0260401c5b6310000000821615614438576801000000000b17217f0260401c5b630800000082161561445357680100000000058b90c00260401c5b630400000082161561446e5768010000000002c5c8600260401c5b6302000000821615614489576801000000000162e4300260401c5b63010000008216156144a45768010000000000b172180260401c5b628000008216156144be576801000000000058b90c0260401c5b624000008216156144d857680100000000002c5c860260401c5b622000008216156144f25768010000000000162e430260401c5b6210000082161561450c57680100000000000b17210260401c5b620800008216156145265768010000000000058b910260401c5b62040000821615614540576801000000000002c5c80260401c5b6202000082161561455a57680100000000000162e40260401c5b620100008216156145735761b172600160401b010260401c5b61800082161561458b576158b9600160401b010260401c5b6140008216156145a357612c5d600160401b010260401c5b6120008216156145bb5761162e600160401b010260401c5b6110008216156145d357610b17600160401b010260401c5b6108008216156145eb5761058c600160401b010260401c5b610400821615614603576102c6600160401b010260401c5b61020082161561461b57610163600160401b010260401c5b6101008216156146325760b1600160401b010260401c5b6080821615614648576059600160401b010260401c5b604082161561465e57602c600160401b010260401c5b6020821615614674576016600160401b010260401c5b601082161561468a57600b600160401b010260401c5b60088216156146a0576006600160401b010260401c5b60048216156146b6576003600160401b010260401c5b60028216156146cc576001600160401b010260401c5b60018216156146e2576001600160401b010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60405180606001604052806000815260200160008152602001600081525090565b6040518060e00160405280600081526020016000815260200161473b61475f565b81526020016000815260200160008152602001600081526020016000151581525090565b604051806040016040528060008152602001600081525090565b6040518061022001604052806147f06040518061014001604052806000801916815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200161481960405180606001604052806000815260200160008152602001600081525090565b81526020016148266148ce565b81526020016148336148a6565b8152602001614840614904565b815260200161484d6148a6565b815260200161485a61475f565b8152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b03811182821017156149665761496661492e565b60405290565b604051608081016001600160401b03811182821017156149665761496661492e565b60405161018081016001600160401b03811182821017156149665761496661492e565b60405161010081016001600160401b03811182821017156149665761496661492e565b604051606081016001600160401b03811182821017156149665761496661492e565b60405161014081016001600160401b03811182821017156149665761496661492e565b604051601f8201601f191681016001600160401b0381118282101715614a4157614a4161492e565b604052919050565b6001600160a01b0381168114614a5e57600080fd5b50565b8035613f9c81614a49565b600060e08284031215614a7e57600080fd5b614a86614944565b90508135614a9381614a49565b81526020820135614aa381614a49565b60208201526040820135614ab681614a49565b60408201526060820135614ac981614a49565b6060820152614ada60808301614a61565b6080820152614aeb60a08301614a61565b60a0820152614afc60c08301614a61565b60c082015292915050565b600060808284031215614b1957600080fd5b614b2161496c565b90508135614b2e81614a49565b81526020820135614b3e81614a49565b60208201526040820135614b5181614a49565b60408201526060820135614b6481614a49565b606082015292915050565b60006001600160401b03821115614b8857614b8861492e565b5060051b60200190565b600082601f830112614ba357600080fd5b8135614bb6614bb182614b6f565b614a19565b8082825260208201915060208360051b860101925085831115614bd857600080fd5b602085015b83811015614bfe578035614bf081614a49565b835260209283019201614bdd565b5095945050505050565b803560098110613f9c57600080fd5b803560038110613f9c57600080fd5b60006101808284031215614c3957600080fd5b614c4161498e565b9050614c4c82614c08565b8152614c5a60208301614c17565b602082015260408281013590820152606080830135908201526080808301359082015260a0808301359082015260c0808301359082015260e080830135908201526101008083013590820152610120808301359082015261014080830135908201526101609182013591810191909152919050565b80358015158114613f9c57600080fd5b600060808284031215614cf157600080fd5b614cf961496c565b9050614d0482614ccf565b8152614d1260208301614ccf565b6020820152614d2360408301614ccf565b6040820152614b6460608301614ccf565b600082601f830112614d4557600080fd5b8135614d53614bb182614b6f565b8082825260208201915060208360051b860101925085831115614d7557600080fd5b602085015b83811015614bfe578035835260209283019201614d7a565b60006102408284031215614da557600080fd5b614dad61496c565b905081356001600160401b03811115614dc557600080fd5b82016101008185031215614dd857600080fd5b614de06149b1565b614de982614a61565b8152614df760208301614a61565b6020820152614e0860408301614a61565b6040820152614e1960608301614a61565b6060820152614e2a60808301614a61565b6080820152614e3b60a08301614a61565b60a0820152614e4c60c08301614a61565b60c082015260e08201356001600160401b03811115614e6a57600080fd5b614e7686828501614b92565b60e083015250825250614e8c8360208401614c26565b6020820152614e9f836101a08401614cdf565b60408201526102208201356001600160401b03811115614ebe57600080fd5b614eca84828501614d34565b60608301525092915050565b600060208284031215614ee857600080fd5b604051602081016001600160401b0381118282101715614f0a57614f0a61492e565b604052905080614f1983614ccf565b905292915050565b60008183036101c0811215614f3557600080fd5b614f3d6149d4565b91506060811215614f4d57600080fd5b614f556149d4565b8335614f6081614a49565b81526020840135614f7081614a49565b60208201526040840135614f8381614a49565b60408201528252610140605f1982011215614f9d57600080fd5b50614fa66149f6565b606083810135825260808085013560208085019190915260a080870135604086015260c0808801359486019490945260e0808801359386019390935261010080880135918601919091526101208088013594860194909452610140870135928501929092526101608601359184019190915261018085013591830191909152820152615036836101a08401614ed6565b604082015292915050565b803560028110613f9c57600080fd5b60006103a0828403121561506357600080fd5b61506b614944565b90506150778383614a6c565b81526150868360e08401614b07565b60208201526101608201356001600160401b038111156150a557600080fd5b6150b184828501614d92565b60408301525061018082013560608201526150d0836101a08401614f21565b608082015261036082013560a0820152614afc6103808301615041565b6000604082840312156150ff57600080fd5b604080519081016001600160401b03811182821017156151215761512161492e565b604052823581526020928301359281019290925250919050565b600060c0828403121561514d57600080fd5b6151556149d4565b905061516183836150ed565b815261517083604084016150ed565b602082015261503683608084016150ed565b60008060e0838503121561519557600080fd5b82356001600160401b038111156151ab57600080fd5b6151b785828601615050565b9250506151c7846020850161513b565b90509250929050565b60008060008061018085870312156151e757600080fd5b84356151f281614a49565b9350602085013561520281614a49565b92506152118660408701614b07565b91506152208660c0870161513b565b905092959194509250565b6000806060838503121561523e57600080fd5b82356001600160401b0381111561525457600080fd5b61526085828601615050565b9250506151c784602085016150ed565b6000806000806000806000610380888a03121561528c57600080fd5b873561529781614a49565b965060208801356152a781614a49565b95506152b68960408a01614f21565b94506152c6896102008a01614b07565b93506152d6896102808a0161513b565b92506152e56103408901614ccf565b91506152f46103608901614ccf565b905092959891949750929550565b6000815180845260005b818110156153285760208185018101518683018201520161530c565b506000602082860101526020601f19601f83011685010191505092915050565b831515815260a06020820152600061536360a0830185615302565b9050825160408301526020830151606083015260408301516080830152949350505050565b6000806000806000808688036102208112156153a357600080fd5b87356153ae81614a49565b96506153bd8960208a01614b07565b95506153cc8960a08a0161513b565b94506101608801356153dd81614a49565b93506153ec6101808901614ccf565b9250608061019f198201121561540157600080fd5b5061540a61496c565b6101a088013581526101c088013560208201526101e088013560408201526102009097013560608801525093969295509093909291565b6000806000806000610340868803121561545a57600080fd5b853561546581614a49565b94506154748760208801614b07565b93506154838760a0880161513b565b9250615493876101608801614f21565b94979396509194610320013592915050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000826154e0576154e06154a5565b600160ff1b8214600019841416156154fa576154fa6154bb565b500590565b60008261550e5761550e6154a5565b500490565b8082018281126000831280158216821582161715615533576155336154bb565b505092915050565b818103600083128015838313168383128216171561555b5761555b6154bb565b5092915050565b918252602082015260400190565b80516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b6155b882825180518252602090810151910152565b602081810151805160408501529081015160608401525060400151805160808301526020015160a090910152565b6001600160a01b03858116825284166020820152610180810161560c6040830185615570565b611bc360c08301846155a3565b6001600160a01b038681168252851660208201526101a0810161563f6040830186615570565b61564c60c08301856155a3565b8215156101808301529695505050505050565b6000600160ff1b8201615674576156746154bb565b5060000390565b808202811582820484141761121a5761121a6154bb565b80820260008212600160ff1b841416156156ae576156ae6154bb565b818105831482151761121a5761121a6154bb565b6000602082840312156156d457600080fd5b5051919050565b6001600160a01b0392831681529116602082015260400190565b6080815260006157086080830187615302565b6020830195909552506040810192909252606090910152919050565b8082018082111561121a5761121a6154bb565b8181038181111561121a5761121a6154bb565b6001600160a01b0391909116815260200190565b60006020828403121561577057600080fd5b815161174781614a49565b6000806040838503121561578e57600080fd5b505080516020909101519092909150565b634e487b7160e01b600052602160045260246000fdfea26469706673582212207f204beb2d6e38f6e795afd435d4b32d914677c62ac22f06171bf326cf87ec7164736f6c634300081d0033", "libraries": { - "MarketStoreUtils": "0xd727120ac811e9136D4a5D5C6219aEE37e275785", - "MarketUtils": "0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96", - "PositionPricingUtils": "0x984Eada4e97CDA510B48BB654A216d3ad47bA362" + "MarketStoreUtils": "0x2e5D10A48C00cFcc6A31af873118d739323Ff71B", + "MarketUtils": "0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB", + "PositionPricingUtils": "0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4" }, "devdoc": { "kind": "dev", diff --git a/deployments/arbitrum/TimelockConfig.json b/deployments/arbitrum/TimelockConfig.json index d511289da..4b48e6ed6 100644 --- a/deployments/arbitrum/TimelockConfig.json +++ b/deployments/arbitrum/TimelockConfig.json @@ -1,5 +1,5 @@ { - "address": "0xC181eB022F33b8ba808AD96348B03e8A753A859b", + "address": "0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1", "abi": [ { "inputs": [ @@ -99,6 +99,17 @@ "name": "EmptyWithdrawalAmount", "type": "error" }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "InvalidContributorToken", + "type": "error" + }, { "inputs": [ { @@ -132,6 +143,22 @@ "name": "InvalidOracleSigner", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokensLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountsLength", + "type": "uint256" + } + ], + "name": "InvalidSetMaxTotalContributorTokenAmountInput", + "type": "error" + }, { "inputs": [ { @@ -154,6 +181,17 @@ "name": "MaxTimelockDelayExceeded", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "interval", + "type": "uint256" + } + ], + "name": "MinContributorPaymentIntervalBelowAllowedRange", + "type": "error" + }, { "inputs": [ { @@ -772,6 +810,67 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "signalSetMaxTotalContributorTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "interval", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "signalSetMinContributorPaymentInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -961,19 +1060,19 @@ "type": "function" } ], - "transactionHash": "0xe3c90ffa9074278a73a79f35345ab05f5881198b23c2c50faea4053a801fede3", + "transactionHash": "0x29d45f39255c957a01e9586f2f4d15c6ce17437ab5f8ad41fca508cd80db354a", "receipt": { "to": null, "from": "0xE7BfFf2aB721264887230037940490351700a068", - "contractAddress": "0xC181eB022F33b8ba808AD96348B03e8A753A859b", - "transactionIndex": 4, - "gasUsed": "5189695", + "contractAddress": "0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1", + "transactionIndex": 22, + "gasUsed": "4447189", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0de9a4aa62d4368afb3ca20dbcc1208fd820d6ddb91ba4e702879e70f8ce1034", - "transactionHash": "0xe3c90ffa9074278a73a79f35345ab05f5881198b23c2c50faea4053a801fede3", + "blockHash": "0x223b01774039a354fed85158605a3ef2cdb1463ac86551a7ec5559948b37c780", + "transactionHash": "0x29d45f39255c957a01e9586f2f4d15c6ce17437ab5f8ad41fca508cd80db354a", "logs": [], - "blockNumber": 367848484, - "cumulativeGasUsed": "6141027", + "blockNumber": 390053972, + "cumulativeGasUsed": "7937996", "status": 1, "byzantium": true }, @@ -982,15 +1081,15 @@ "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", "0xA8AF9B86fC47deAde1bc66B12673706615E2B011", "0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72", - "0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621" + "0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f" ], - "numDeployments": 4, - "solcInputHash": "1085fa0bbd9d8812a88d39eedbba618e", - "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"_eventEmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dataStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_oracleStore\",\"type\":\"address\"},{\"internalType\":\"contract RoleStore\",\"name\":\"_roleStore\",\"type\":\"address\"},{\"internalType\":\"contract ConfigTimelockController\",\"name\":\"_timelockController\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"baseKey\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"ConfigValueExceedsAllowedRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"EmptyDataStreamFeedId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyFundingAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyMarket\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPositionImpactWithdrawalAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReduceLentAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyWithdrawalAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"InvalidFeeReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"InvalidHoldingAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidOracleSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timelockDelay\",\"type\":\"uint256\"}],\"name\":\"InvalidTimelockDelay\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timelockDelay\",\"type\":\"uint256\"}],\"name\":\"MaxTimelockDelayExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"role\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MAX_TIMELOCK_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"cancelAction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dataStore\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventEmitter\",\"outputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"providers\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct OracleUtils.SetPricesParams\",\"name\":\"oracleParams\",\"type\":\"tuple\"}],\"name\":\"executeWithOraclePrice\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"getHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"getHashBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timelockDelay\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"increaseTimelockDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleStore\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"roleKey\",\"type\":\"bytes32\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"roleStore\",\"outputs\":[{\"internalType\":\"contract RoleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalAddOracleSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"roleKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalGrantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fundingAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"reductionAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalReduceLentAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalRemoveOracleSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"roleKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalRevokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetAtomicOracleProvider\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dataStreamMultiplier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataStreamSpreadReductionFactor\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetDataStream\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"edgeDataStreamId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"edgeDataStreamTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetEdgeDataStream\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetFeeReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetHoldingAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetOracleProviderEnabled\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetOracleProviderForToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"priceFeedMultiplier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"priceFeedHeartbeatDuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"stablePrice\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetPriceFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalWithdrawFromPositionImpactPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalWithdrawTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timelockController\",\"outputs\":[{\"internalType\":\"contract ConfigTimelockController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"multicall(bytes[])\":{\"details\":\"Receives and executes a batch of function calls on this contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/config/TimelockConfig.sol\":\"TimelockConfig\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorInterface {\\n function latestAnswer() external view returns (int256);\\n\\n function latestTimestamp() external view returns (uint256);\\n\\n function latestRound() external view returns (uint256);\\n\\n function getAnswer(uint256 roundId) external view returns (int256);\\n\\n function getTimestamp(uint256 roundId) external view returns (uint256);\\n\\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\\n\\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\\n}\\n\",\"keccak256\":\"0xb496651006b9a2a07920ffe116928b11e2a6458e21361cecca51409522488ca7\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {AggregatorInterface} from \\\"./AggregatorInterface.sol\\\";\\nimport {AggregatorV3Interface} from \\\"./AggregatorV3Interface.sol\\\";\\n\\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\\n\",\"keccak256\":\"0xee12d80dbdbb3cc0ec10372b9323e42fae9a6de45da5a4e9f7a75223a0b5268b\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n function getRoundData(\\n uint80 _roundId\\n ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n\\n function latestRoundData()\\n external\\n view\\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n}\\n\",\"keccak256\":\"0xfe4e8bb4861bb3860ba890ab91a3b818ec66e5a8f544fb608cfcb73f433472cd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```solidity\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```solidity\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\\n * to enforce additional security measures for this role.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role);\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\\n * Overriding this function changes the behavior of the {onlyRole} modifier.\\n *\\n * Format of the revert message is described in {_checkRole}.\\n *\\n * _Available since v4.6._\\n */\\n function _checkRole(bytes32 role) internal view virtual {\\n _checkRole(role, _msgSender());\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view virtual {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(account),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * May emit a {RoleGranted} event.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n *\\n * NOTE: This function is deprecated in favor of {_grantRole}.\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n bytes32 previousAdminRole = getRoleAdmin(role);\\n _roles[role].adminRole = adminRole;\\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function _grantRole(bytes32 role, address account) internal virtual {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function _revokeRole(bytes32 role, address account) internal virtual {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0dd6e52cb394d7f5abe5dca2d4908a6be40417914720932de757de34a99ab87f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/governance/TimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../access/AccessControl.sol\\\";\\nimport \\\"../token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"../token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Contract module which acts as a timelocked controller. When set as the\\n * owner of an `Ownable` smart contract, it enforces a timelock on all\\n * `onlyOwner` maintenance operations. This gives time for users of the\\n * controlled contract to exit before a potentially dangerous maintenance\\n * operation is applied.\\n *\\n * By default, this contract is self administered, meaning administration tasks\\n * have to go through the timelock process. The proposer (resp executor) role\\n * is in charge of proposing (resp executing) operations. A common use case is\\n * to position this {TimelockController} as the owner of a smart contract, with\\n * a multisig or a DAO as the sole proposer.\\n *\\n * _Available since v3.3._\\n */\\ncontract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {\\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\\\"TIMELOCK_ADMIN_ROLE\\\");\\n bytes32 public constant PROPOSER_ROLE = keccak256(\\\"PROPOSER_ROLE\\\");\\n bytes32 public constant EXECUTOR_ROLE = keccak256(\\\"EXECUTOR_ROLE\\\");\\n bytes32 public constant CANCELLER_ROLE = keccak256(\\\"CANCELLER_ROLE\\\");\\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\\n\\n mapping(bytes32 => uint256) private _timestamps;\\n uint256 private _minDelay;\\n\\n /**\\n * @dev Emitted when a call is scheduled as part of operation `id`.\\n */\\n event CallScheduled(\\n bytes32 indexed id,\\n uint256 indexed index,\\n address target,\\n uint256 value,\\n bytes data,\\n bytes32 predecessor,\\n uint256 delay\\n );\\n\\n /**\\n * @dev Emitted when a call is performed as part of operation `id`.\\n */\\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\\n\\n /**\\n * @dev Emitted when new proposal is scheduled with non-zero salt.\\n */\\n event CallSalt(bytes32 indexed id, bytes32 salt);\\n\\n /**\\n * @dev Emitted when operation `id` is cancelled.\\n */\\n event Cancelled(bytes32 indexed id);\\n\\n /**\\n * @dev Emitted when the minimum delay for future operations is modified.\\n */\\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\\n\\n /**\\n * @dev Initializes the contract with the following parameters:\\n *\\n * - `minDelay`: initial minimum delay for operations\\n * - `proposers`: accounts to be granted proposer and canceller roles\\n * - `executors`: accounts to be granted executor role\\n * - `admin`: optional account to be granted admin role; disable with zero address\\n *\\n * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment\\n * without being subject to delay, but this role should be subsequently renounced in favor of\\n * administration through timelocked proposals. Previous versions of this contract would assign\\n * this admin to the deployer automatically and should be renounced as well.\\n */\\n constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {\\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);\\n\\n // self administration\\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\\n\\n // optional admin\\n if (admin != address(0)) {\\n _setupRole(TIMELOCK_ADMIN_ROLE, admin);\\n }\\n\\n // register proposers and cancellers\\n for (uint256 i = 0; i < proposers.length; ++i) {\\n _setupRole(PROPOSER_ROLE, proposers[i]);\\n _setupRole(CANCELLER_ROLE, proposers[i]);\\n }\\n\\n // register executors\\n for (uint256 i = 0; i < executors.length; ++i) {\\n _setupRole(EXECUTOR_ROLE, executors[i]);\\n }\\n\\n _minDelay = minDelay;\\n emit MinDelayChange(0, minDelay);\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only by a certain role. In\\n * addition to checking the sender's role, `address(0)` 's role is also\\n * considered. Granting a role to `address(0)` is equivalent to enabling\\n * this role for everyone.\\n */\\n modifier onlyRoleOrOpenRole(bytes32 role) {\\n if (!hasRole(role, address(0))) {\\n _checkRole(role, _msgSender());\\n }\\n _;\\n }\\n\\n /**\\n * @dev Contract might receive/hold ETH as part of the maintenance process.\\n */\\n receive() external payable {}\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns whether an id correspond to a registered operation. This\\n * includes both Pending, Ready and Done operations.\\n */\\n function isOperation(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > 0;\\n }\\n\\n /**\\n * @dev Returns whether an operation is pending or not. Note that a \\\"pending\\\" operation may also be \\\"ready\\\".\\n */\\n function isOperationPending(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns whether an operation is ready for execution. Note that a \\\"ready\\\" operation is also \\\"pending\\\".\\n */\\n function isOperationReady(bytes32 id) public view virtual returns (bool) {\\n uint256 timestamp = getTimestamp(id);\\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\\n }\\n\\n /**\\n * @dev Returns whether an operation is done or not.\\n */\\n function isOperationDone(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) == _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns the timestamp at which an operation becomes ready (0 for\\n * unset operations, 1 for done operations).\\n */\\n function getTimestamp(bytes32 id) public view virtual returns (uint256) {\\n return _timestamps[id];\\n }\\n\\n /**\\n * @dev Returns the minimum delay for an operation to become valid.\\n *\\n * This value can be changed by executing an operation that calls `updateDelay`.\\n */\\n function getMinDelay() public view virtual returns (uint256) {\\n return _minDelay;\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a single\\n * transaction.\\n */\\n function hashOperation(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(target, value, data, predecessor, salt));\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a batch of\\n * transactions.\\n */\\n function hashOperationBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(targets, values, payloads, predecessor, salt));\\n }\\n\\n /**\\n * @dev Schedule an operation containing a single transaction.\\n *\\n * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function schedule(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\\n _schedule(id, delay);\\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation containing a batch of transactions.\\n *\\n * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function scheduleBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n _schedule(id, delay);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);\\n }\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation that is to become valid after a given delay.\\n */\\n function _schedule(bytes32 id, uint256 delay) private {\\n require(!isOperation(id), \\\"TimelockController: operation already scheduled\\\");\\n require(delay >= getMinDelay(), \\\"TimelockController: insufficient delay\\\");\\n _timestamps[id] = block.timestamp + delay;\\n }\\n\\n /**\\n * @dev Cancel an operation.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'canceller' role.\\n */\\n function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {\\n require(isOperationPending(id), \\\"TimelockController: operation cannot be cancelled\\\");\\n delete _timestamps[id];\\n\\n emit Cancelled(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a single transaction.\\n *\\n * Emits a {CallExecuted} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function execute(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n bytes32 id = hashOperation(target, value, payload, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n _execute(target, value, payload);\\n emit CallExecuted(id, 0, target, value, payload);\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a batch of transactions.\\n *\\n * Emits one {CallExecuted} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n address target = targets[i];\\n uint256 value = values[i];\\n bytes calldata payload = payloads[i];\\n _execute(target, value, payload);\\n emit CallExecuted(id, i, target, value, payload);\\n }\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an operation's call.\\n */\\n function _execute(address target, uint256 value, bytes calldata data) internal virtual {\\n (bool success, ) = target.call{value: value}(data);\\n require(success, \\\"TimelockController: underlying transaction reverted\\\");\\n }\\n\\n /**\\n * @dev Checks before execution of an operation's calls.\\n */\\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \\\"TimelockController: missing dependency\\\");\\n }\\n\\n /**\\n * @dev Checks after execution of an operation's calls.\\n */\\n function _afterCall(bytes32 id) private {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n _timestamps[id] = _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Changes the minimum timelock duration for future operations.\\n *\\n * Emits a {MinDelayChange} event.\\n *\\n * Requirements:\\n *\\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\\n */\\n function updateDelay(uint256 newDelay) external virtual {\\n require(msg.sender == address(this), \\\"TimelockController: caller must be timelock\\\");\\n emit MinDelayChange(_minDelay, newDelay);\\n _minDelay = newDelay;\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xda2a70247fda81633d9392f567a401c4772837de6b0543c1c561ca632a2fe7f4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/config/ConfigTimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {EventUtils} from \\\"../event/EventUtils.sol\\\";\\nimport {Multicall3} from \\\"../mock/Multicall3.sol\\\";\\nimport {OracleStore} from \\\"../oracle/OracleStore.sol\\\";\\nimport {RoleStore} from \\\"../role/RoleStore.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {TimelockController} from \\\"@openzeppelin/contracts/governance/TimelockController.sol\\\";\\nimport {OracleModule} from \\\"../oracle/OracleModule.sol\\\";\\nimport {OracleUtils} from \\\"../oracle/OracleUtils.sol\\\";\\nimport {Oracle} from \\\"../oracle/Oracle.sol\\\";\\nimport {PositionImpactPoolUtils} from \\\"../market/PositionImpactPoolUtils.sol\\\";\\nimport {Chain} from \\\"../chain/Chain.sol\\\";\\nimport {AccountUtils} from \\\"../utils/AccountUtils.sol\\\";\\n\\ncontract ConfigTimelockController is TimelockController, OracleModule {\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n\\n constructor(\\n uint256 minDelay,\\n address[] memory proposers,\\n address[] memory executors,\\n Oracle oracle,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter\\n ) TimelockController(minDelay, proposers, executors, msg.sender) OracleModule(oracle) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n }\\n\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n // note that if on-chain prices are used for market operations, there may\\n // be some difference in pricing between the on-chain price and e.g.\\n // an off-chain data stream price\\n // it should be ensured that the changes to the market token price that\\n // result from this execution are not too large that it would lead to\\n // significant arbitrage opportunities\\n function executeWithOraclePrices(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt,\\n OracleUtils.SetPricesParams calldata oracleParams\\n ) external onlyRoleOrOpenRole(EXECUTOR_ROLE) withOraclePricesForAtomicAction(oracleParams) {\\n execute(target, value, payload, predecessor, salt);\\n }\\n\\n function withdrawFromPositionImpactPool(\\n address market,\\n address receiver,\\n uint256 amount\\n ) external onlySelf {\\n PositionImpactPoolUtils.withdrawFromPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentImpactAmount(\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external onlySelf {\\n PositionImpactPoolUtils.reduceLentAmount(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n fundingAccount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xfd4e8cf25c70dc3e8b14f59067edbacd134a7e3a1294250f7b0392049b51ddbf\",\"license\":\"BUSL-1.1\"},\"contracts/config/TimelockConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {EventUtils} from \\\"../event/EventUtils.sol\\\";\\nimport {RoleModule} from \\\"../role/RoleModule.sol\\\";\\nimport {RoleStore} from \\\"../role/RoleStore.sol\\\";\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {BasicMulticall} from \\\"../utils/BasicMulticall.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {ConfigTimelockController} from \\\"./ConfigTimelockController.sol\\\";\\nimport {OracleModule} from \\\"../oracle/OracleModule.sol\\\";\\nimport {OracleUtils} from \\\"../oracle/OracleUtils.sol\\\";\\nimport {MarketUtils} from \\\"../market/MarketUtils.sol\\\";\\n\\ncontract TimelockConfig is RoleModule, BasicMulticall {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n uint256 public constant MAX_TIMELOCK_DELAY = 5 days;\\n\\n EventEmitter public immutable eventEmitter;\\n ConfigTimelockController public immutable timelockController;\\n\\n address public immutable dataStore;\\n address public immutable oracleStore;\\n\\n constructor(\\n EventEmitter _eventEmitter,\\n address _dataStore,\\n address _oracleStore,\\n RoleStore _roleStore,\\n ConfigTimelockController _timelockController\\n ) RoleModule(_roleStore) {\\n eventEmitter = _eventEmitter;\\n dataStore = _dataStore;\\n oracleStore = _oracleStore;\\n timelockController = _timelockController;\\n }\\n\\n // @dev signal granting of a role\\n // @param account the account to grant the role\\n // @param roleKey the role to grant\\n function signalGrantRole(address account, bytes32 roleKey, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"grantRole(address,bytes32)\\\", account, roleKey);\\n timelockController.schedule(address(roleStore), 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"roleKey\\\", roleKey);\\n _signalPendingAction(\\n \\\"SignalGrantRole\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal revoking of a role\\n // @param account the account to revoke the role for\\n // @param roleKey the role to revoke\\n function signalRevokeRole(address account, bytes32 roleKey, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"revokeRole(address,bytes32)\\\",\\n account, roleKey);\\n timelockController.schedule(address(roleStore), 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"roleKey\\\", roleKey);\\n _signalPendingAction(\\n \\\"SignalRevokeRole\\\",\\n eventData\\n );\\n }\\n\\n // @dev immediately revoke the role of an account\\n // @param account the account to revoke the role for\\n // @param roleKey the role to revoke\\n function revokeRole(address account, bytes32 roleKey) external onlyTimelockMultisig {\\n roleStore.revokeRole(account, roleKey);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"roleKey\\\", roleKey);\\n _signalPendingAction(\\n \\\"RevokeRole\\\",\\n eventData\\n );\\n }\\n\\n function signalSetOracleProviderEnabled(address provider, bool value, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"setBool(bytes32,bool)\\\",\\n Keys.isOracleProviderEnabledKey(provider), value);\\n timelockController.schedule(dataStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"provider\\\", provider);\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"value\\\", value);\\n _signalPendingAction(\\n \\\"SignalSetOracleProviderEnabled\\\",\\n eventData\\n );\\n }\\n\\n function signalSetOracleProviderForToken(address oracle, address token, address provider, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.oracleProviderForTokenKey(oracle, token), provider);\\n timelockController.schedule(dataStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"oracle\\\", oracle);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"provider\\\", provider);\\n _signalPendingAction(\\n \\\"SignalSetOracleProviderForToken\\\",\\n eventData\\n );\\n }\\n\\n function signalSetAtomicOracleProvider(address provider, bool value, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"setBool(bytes32,bool)\\\",\\n Keys.isAtomicOracleProviderKey(provider), value);\\n timelockController.schedule(dataStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"provider\\\", provider);\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"value\\\", value);\\n _signalPendingAction(\\n \\\"SignalSetAtomicOracleProvider\\\",\\n eventData\\n );\\n }\\n\\n function signalAddOracleSigner(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidOracleSigner(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"addSigner(address)\\\", account);\\n timelockController.schedule(oracleStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalAddOracleSigner\\\",\\n eventData\\n );\\n }\\n\\n function signalRemoveOracleSigner(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidOracleSigner(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"removeSigner(address)\\\", account);\\n timelockController.schedule(oracleStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalRemoveOracleSigner\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of the fee receiver\\n // @param account the new fee receiver\\n function signalSetFeeReceiver(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidFeeReceiver(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.FEE_RECEIVER, account);\\n timelockController.schedule(dataStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalSetFeeReceiver\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of the holding address\\n // @param account of the new holding address\\n function signalSetHoldingAddress(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidHoldingAddress(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.HOLDING_ADDRESS, account);\\n timelockController.schedule(dataStore, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalSetHoldingAddress\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of a price feed\\n // @param token the token to set the price feed for\\n // @param priceFeed the address of the price feed\\n // @param priceFeedMultiplier the multiplier to apply to the price feed results\\n // @param stablePrice the stable price to set a range for the price feed results\\n function signalSetPriceFeed(\\n address token,\\n address priceFeed,\\n uint256 priceFeedMultiplier,\\n uint256 priceFeedHeartbeatDuration,\\n uint256 stablePrice,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n\\n address[] memory targets = new address[](4);\\n targets[0] = dataStore;\\n targets[1] = dataStore;\\n targets[2] = dataStore;\\n targets[3] = dataStore;\\n\\n bytes[] memory payloads = new bytes[](4);\\n payloads[0] = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.priceFeedKey(token), priceFeed);\\n payloads[1] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.priceFeedMultiplierKey(token), priceFeedMultiplier);\\n payloads[2] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration);\\n payloads[3] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.stablePriceKey(token), stablePrice);\\n\\n uint256[] memory values = new uint256[](4);\\n timelockController.scheduleBatch(targets, values, payloads, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"priceFeed\\\", priceFeed);\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"priceFeedMultiplier\\\", priceFeedMultiplier);\\n eventData.uintItems.setItem(1, \\\"priceFeedHeartbeatDuration\\\", priceFeedHeartbeatDuration);\\n eventData.uintItems.setItem(2, \\\"stablePrice\\\", stablePrice);\\n _signalPendingAction(\\n \\\"SignalSetPriceFeed\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of a data stream feed\\n // @param token the token to set the data stream feed for\\n // @param feedId the ID of the data stream feed\\n // @param dataStreamMultiplier the multiplier to apply to the data stream feed results\\n // @param dataStreamSpreadReductionFactor the factor to apply to the data stream price spread\\n function signalSetDataStream(\\n address token,\\n bytes32 feedId,\\n uint256 dataStreamMultiplier,\\n uint256 dataStreamSpreadReductionFactor,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (dataStreamSpreadReductionFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.ConfigValueExceedsAllowedRange(Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR, dataStreamSpreadReductionFactor);\\n }\\n\\n address[] memory targets = new address[](3);\\n targets[0] = dataStore;\\n targets[1] = dataStore;\\n targets[2] = dataStore;\\n\\n bytes[] memory payloads = new bytes[](3);\\n payloads[0] = abi.encodeWithSignature(\\\"setBytes32(bytes32,bytes32)\\\",\\n Keys.dataStreamIdKey(token), feedId);\\n payloads[1] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.dataStreamMultiplierKey(token), dataStreamMultiplier);\\n payloads[2] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.dataStreamSpreadReductionFactorKey(token), dataStreamSpreadReductionFactor);\\n\\n uint256[] memory values = new uint256[](3);\\n timelockController.scheduleBatch(targets, values, payloads, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"feedId\\\", feedId);\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"dataStreamMultiplier\\\", dataStreamMultiplier);\\n eventData.uintItems.setItem(1, \\\"dataStreamSpreadReductionFactor\\\", dataStreamSpreadReductionFactor);\\n _signalPendingAction(\\n \\\"SignalSetDataStream\\\",\\n eventData\\n );\\n }\\n\\n // @dev increase the timelock delay\\n // @param the new timelock delay\\n function increaseTimelockDelay(uint256 _timelockDelay, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (_timelockDelay <= timelockController.getMinDelay()) {\\n revert Errors.InvalidTimelockDelay(_timelockDelay);\\n }\\n\\n if (_timelockDelay > MAX_TIMELOCK_DELAY) {\\n revert Errors.MaxTimelockDelayExceeded(_timelockDelay);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"updateDelay(uint256)\\\", _timelockDelay);\\n timelockController.schedule(\\n address(timelockController),\\n 0,\\n payload,\\n predecessor,\\n salt,\\n timelockController.getMinDelay()\\n );\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"timelockDelay\\\", _timelockDelay);\\n _signalPendingAction(\\n \\\"IncreaseTimelockDelay\\\",\\n eventData\\n );\\n }\\n\\n function signalReduceLentAmount(\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (market == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n if (fundingAccount == address(0)) {\\n revert Errors.EmptyFundingAccount();\\n }\\n if (reductionAmount == 0) {\\n revert Errors.EmptyReduceLentAmount();\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"reduceLentImpactAmount(address,address,uint256)\\\",\\n market, fundingAccount, reductionAmount);\\n timelockController.schedule(address(timelockController), 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"reductionAmount\\\", reductionAmount);\\n _signalPendingAction(\\n \\\"SignalReduceLentImpactAmount\\\",\\n eventData\\n );\\n }\\n\\n // @dev Withdraw funds from position impact pool(negative price impacts) and send them to `receiver`\\n // @param market Market from withdraw\\n // @param receiver Account to send funds from pool\\n // @param amount Amount of tokens to withdraw\\n function signalWithdrawFromPositionImpactPool(\\n address market,\\n address receiver,\\n uint256 amount,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (market == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n if (amount == 0) {\\n revert Errors.EmptyPositionImpactWithdrawalAmount();\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"withdrawFromPositionImpactPool(address,address,uint256)\\\",\\n market, receiver, amount);\\n timelockController.schedule(address(timelockController), 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n _signalPendingAction(\\n \\\"SignalWithdrawFromPositionImpactPool\\\",\\n eventData\\n );\\n }\\n\\n function signalWithdrawTokens(\\n address target,\\n address token,\\n address receiver,\\n uint256 amount,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (target == address(0)) {\\n revert Errors.EmptyTarget();\\n }\\n if (token == address(0)) {\\n revert Errors.EmptyToken();\\n }\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n if (amount == 0) {\\n revert Errors.EmptyWithdrawalAmount();\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"withdrawTokens(address,address,uint256)\\\",\\n token,\\n receiver,\\n amount\\n );\\n timelockController.schedule(target, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"target\\\", target);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n _signalPendingAction(\\\"SignalWithdrawTokens\\\", eventData);\\n }\\n\\n function signalSetEdgeDataStream(\\n address token,\\n bytes32 edgeDataStreamId,\\n uint256 edgeDataStreamTokenDecimals,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (edgeDataStreamId == bytes32(0)) {\\n revert Errors.EmptyDataStreamFeedId(token);\\n }\\n\\n address[] memory targets = new address[](2);\\n targets[0] = dataStore;\\n targets[1] = dataStore;\\n\\n bytes[] memory payloads = new bytes[](2);\\n payloads[0] = abi.encodeWithSignature(\\\"setBytes32(bytes32,bytes32)\\\",\\n Keys.edgeDataStreamIdKey(token), edgeDataStreamId);\\n payloads[1] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.edgeDataStreamTokenDecimalsKey(token), edgeDataStreamTokenDecimals);\\n\\n uint256[] memory values = new uint256[](2);\\n timelockController.scheduleBatch(targets, values, payloads, predecessor, salt, timelockController.getMinDelay());\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"edgeDataStreamId\\\", edgeDataStreamId);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"edgeDataStreamTokenDecimals\\\", edgeDataStreamTokenDecimals);\\n\\n _signalPendingAction(\\\"SignalSetEdgeDataStream\\\", eventData);\\n }\\n\\n function execute(address target, bytes calldata payload, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n timelockController.execute(target, 0, payload, predecessor, salt);\\n }\\n\\n function executeWithOraclePrice(\\n address target,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt,\\n OracleUtils.SetPricesParams calldata oracleParams\\n ) external onlyTimelockAdmin {\\n timelockController.executeWithOraclePrices(\\n target, 0, payload, predecessor, salt, oracleParams\\n );\\n }\\n\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n timelockController.executeBatch(targets, values, payloads, predecessor, salt);\\n }\\n\\n function getHash(address target, bytes calldata payload, bytes32 predecessor, bytes32 salt) external view returns (bytes32) {\\n return timelockController.hashOperation(target, 0, payload, predecessor, salt);\\n }\\n\\n function getHashBatch(\\n address[] calldata targets,\\n bytes[] calldata payloads,\\n uint256[] calldata values,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external view returns (bytes32) {\\n return timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt);\\n }\\n\\n function cancelAction(bytes32 id) external onlyTimelockAdmin {\\n timelockController.cancel(id);\\n }\\n\\n function _signalPendingAction(string memory actionLabel, EventUtils.EventLogData memory eventData) internal {\\n EventUtils.EventLogData memory actionData;\\n\\n bytes32 actionKey = keccak256(abi.encode(actionLabel));\\n\\n actionData.bytes32Items.initItems(1);\\n actionData.bytes32Items.setItem(0, \\\"actionKey\\\", actionKey);\\n\\n actionData.stringItems.initItems(1);\\n actionData.stringItems.setItem(0, \\\"actionLabel\\\", actionLabel);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignalPendingAction\\\",\\n actionKey,\\n actionData\\n );\\n\\n eventEmitter.emitEventLog(\\n actionLabel,\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x111f715006a476bd782701865f2c016ac4582d6d2ba42be39dab24d453d6cb21\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n // @dev key for the contributor account list\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n // @dev key for the contributor token list\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n // @dev key for the contributor token amount\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the max total contributor token amount\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n // @dev key for the contributor token vault\\n bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_VAULT\\\"));\\n // @dev key for the contributor last payment at\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n // @dev key for the min contributor payment interval\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the contributor token vault\\n // @param token the contributor token\\n // @return key for the contributor token vault\\n function contributorTokenVaultKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_VAULT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x7fac6b37f94667534dc57b81a7c5a99bb100c87810405e7941883051f3faca78\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n}\\n\",\"keccak256\":\"0xbd1dedfc1eec03422dcf70c598c4ff56d033d24727cec10601243f2e1c479c54\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x301b8df4bd9f7cd46804d6a732e8f092b59fda0450c59ef33845eda262f5e6d5\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/market/PositionImpactPoolUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {Market} from \\\"./Market.sol\\\";\\nimport {MarketEventUtils} from \\\"./MarketEventUtils.sol\\\";\\nimport {MarketPoolValueInfo} from \\\"./MarketPoolValueInfo.sol\\\";\\nimport {MarketStoreUtils} from \\\"./MarketStoreUtils.sol\\\";\\nimport {MarketToken} from \\\"./MarketToken.sol\\\";\\nimport {MarketUtils} from \\\"./MarketUtils.sol\\\";\\nimport {SafeCast} from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IOracle } from \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../position/PositionUtils.sol\\\";\\n\\nlibrary PositionImpactPoolUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n using SafeERC20 for IERC20;\\n\\n using Market for Market.Props;\\n\\n // @dev withdraw funds from the position impact pool while maintaining GM token price\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param receiver the address to receive the withdrawn funds\\n // @param amount the amount to withdraw\\n // @param oracle - oracle to fetch the market prices\\n function withdrawFromPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n require(amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n MarketUtils.distributePositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market\\n );\\n\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\\n dataStore,\\n marketProps,\\n prices.indexTokenPrice,\\n prices.longTokenPrice,\\n prices.shortTokenPrice,\\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\\n false\\n );\\n\\n if (poolValueInfo.poolValue <= 0) {\\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\\n }\\n\\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\\n\\n // if there is a positive totalPendingImpactAmount, that means that the\\n // excess should be covered by the position impact pool, so subtract this\\n // from the impactPoolAmount that can be withdrawn\\n // lent amount is not considered here, because if there is a lent amount\\n // we assume that the position impact would be zero\\n if (totalPendingImpactAmount > 0) {\\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\\n }\\n\\n if (adjustedImpactPoolAmount < amount) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n MarketUtils.applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n - amount.toInt256()\\n );\\n\\n // Calculate amount of tokens to withdraw:\\n // We want to withdraw long and short tokens from the pool\\n // at the current pool token ratio\\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\\n dataStore,\\n marketProps,\\n prices,\\n amount * prices.indexTokenPrice.min\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n - longTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n - shortTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.longToken,\\n receiver,\\n longTokenWithdrawalAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.shortToken,\\n receiver,\\n shortTokenWithdrawalAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\\n eventEmitter,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external {\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\\n\\n if (reductionAmount > lentAmount) {\\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\\n }\\n\\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\\n\\n if (longTokenAmount > 0) {\\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\\n }\\n\\n if (shortTokenAmount > 0) {\\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\\n }\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n longTokenAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n shortTokenAmount.toInt256()\\n );\\n\\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitLentImpactAmountReduction(\\n eventEmitter,\\n market,\\n fundingAccount,\\n longTokenAmount,\\n shortTokenAmount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe74b2dfdd27d92eb33535d5c5fe4af456d05c180d17d8252f5728c62dd1293b0\",\"license\":\"BUSL-1.1\"},\"contracts/mock/Multicall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title Multicall3\\n/// @notice Aggregate results from multiple function calls\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract Multicall3 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked { valAccumulator += val; }\\n (result.success, result.returnData) = calli.target.call{value: val}(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked { ++i; }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x403295008f09f7f5911396b6243d95bd4084e8f6e085af2b958a4af64c29e07c\",\"license\":\"MIT\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/ChainlinkPriceFeedUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./IPriceFeed.sol\\\";\\n\\n// @title ChainlinkPriceFeedProviderUtils\\n// @dev Library for Chainlink price feed\\nlibrary ChainlinkPriceFeedUtils {\\n // there is a small risk of stale pricing due to latency in price updates or if the chain is down\\n // this is meant to be for temporary use until low latency price feeds are supported for all tokens\\n function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {\\n address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));\\n if (priceFeedAddress == address(0)) {\\n return (false, 0);\\n }\\n\\n IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);\\n\\n (\\n /* uint80 roundID */,\\n int256 _price,\\n /* uint256 startedAt */,\\n uint256 timestamp,\\n /* uint80 answeredInRound */\\n ) = priceFeed.latestRoundData();\\n\\n if (_price <= 0) {\\n revert Errors.InvalidFeedPrice(token, _price);\\n }\\n\\n uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));\\n if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {\\n revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);\\n }\\n\\n uint256 price = SafeCast.toUint256(_price);\\n uint256 precision = getPriceFeedMultiplier(dataStore, token);\\n\\n uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);\\n\\n return (true, adjustedPrice);\\n }\\n\\n // @dev get the multiplier value to convert the external price feed price to the price of 1 unit of the token\\n // represented with 30 decimals\\n // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of\\n // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)\\n // if the external price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8)\\n // in this case the priceFeedMultiplier should be 10 ^ 46\\n // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24)\\n // formula for decimals for price feed multiplier: 60 - (external price feed decimals) - (token decimals)\\n //\\n // @param dataStore DataStore\\n // @param token the token to get the price feed multiplier for\\n // @return the price feed multipler\\n function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {\\n uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));\\n\\n if (multiplier == 0) {\\n revert Errors.EmptyChainlinkPriceFeedMultiplier(token);\\n }\\n\\n return multiplier;\\n }\\n}\\n\",\"keccak256\":\"0xf2abeec57d21410a8306356562077b0aedb77f15be6a5d1451c915c0c20b2fe6\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OracleUtils.sol\\\";\\n\\n// @title IOracleProvider\\n// @dev Interface for an oracle provider\\ninterface IOracleProvider {\\n function getOraclePrice(\\n address token,\\n bytes memory data\\n ) external returns (OracleUtils.ValidatedPrice memory);\\n\\n /// @dev for all oracle providers besides ChainlinkPriceFeedProvider\\n function shouldAdjustTimestamp() external pure returns (bool);\\n\\n /// @dev for ChainlinkPriceFeedProvider\\n function isChainlinkOnChainProvider() external pure returns (bool);\\n}\\n\",\"keccak256\":\"0x8d58f6373f8894c71e559e845db06043047c4ccdf9fac827f8cdf41044b3b1f6\",\"license\":\"MIT\"},\"contracts/oracle/IPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n// @title IPriceFeed\\n// @dev Interface for a price feed\\ninterface IPriceFeed {\\n function latestRoundData() external view returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function description() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x5474d86a80fde875ffd0b52d2806554b32bf10c33553ecae7de1f82400bcf5b6\",\"license\":\"MIT\"},\"contracts/oracle/Oracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport { AggregatorV2V3Interface } from \\\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\\\";\\n\\nimport \\\"../role/RoleModule.sol\\\";\\n\\nimport \\\"./OracleUtils.sol\\\";\\nimport \\\"./IOracle.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\nimport \\\"./ChainlinkPriceFeedUtils.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\nimport \\\"../utils/Uint256Mask.sol\\\";\\n\\n// @title Oracle\\n// @dev Contract to validate and store signed values\\n// Some calculations e.g. calculating the size in tokens for a position\\n// may not work with zero / negative prices\\n// as a result, zero / negative prices are considered empty / invalid\\n// A market may need to be manually settled in this case\\ncontract Oracle is IOracle, RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using Price for Price.Props;\\n using Uint256Mask for Uint256Mask.Mask;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n AggregatorV2V3Interface public immutable sequencerUptimeFeed;\\n\\n // tokensWithPrices stores the tokens with prices that have been set\\n // this is used in clearAllPrices to help ensure that all token prices\\n // set in setPrices are cleared after use\\n EnumerableSet.AddressSet internal tokensWithPrices;\\n mapping(address => Price.Props) public primaryPrices;\\n\\n uint256 public minTimestamp;\\n uint256 public maxTimestamp;\\n\\n constructor(\\n RoleStore _roleStore,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter,\\n AggregatorV2V3Interface _sequencerUptimeFeed\\n ) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n sequencerUptimeFeed = _sequencerUptimeFeed;\\n }\\n\\n // this can be used to help ensure that on-chain prices are updated\\n // before actions dependent on those on-chain prices are allowed\\n // additionally, this can also be used to provide a grace period for\\n // users to top up collateral before liquidations occur\\n function validateSequencerUp() public view {\\n if (address(sequencerUptimeFeed) == address(0)) {\\n return;\\n }\\n\\n (\\n /*uint80 roundID*/,\\n int256 answer,\\n uint256 startedAt,\\n /*uint256 updatedAt*/,\\n /*uint80 answeredInRound*/\\n ) = sequencerUptimeFeed.latestRoundData();\\n\\n // answer == 0: sequencer is up\\n // answer == 1: sequencer is down\\n bool isSequencerUp = answer == 0;\\n if (!isSequencerUp) {\\n revert Errors.SequencerDown();\\n }\\n\\n uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);\\n\\n // ensure the grace duration has passed after the\\n // sequencer is back up.\\n uint256 timeSinceUp = block.timestamp - startedAt;\\n if (timeSinceUp <= sequencerGraceDuration) {\\n revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);\\n }\\n }\\n\\n function setPrices(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);\\n\\n _setPrices(prices);\\n }\\n\\n function setPricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n validateSequencerUp();\\n\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);\\n\\n _setPrices(prices);\\n }\\n\\n // @dev set the primary price\\n // @param token the token to set the price for\\n // @param price the price value to set to\\n function setPrimaryPrice(address token, Price.Props memory price) external onlyController {\\n _setPrimaryPrice(token, price);\\n }\\n\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n // @dev clear all prices\\n function clearAllPrices() external onlyController {\\n uint256 length = tokensWithPrices.length();\\n for (uint256 i; i < length; i++) {\\n address token = tokensWithPrices.at(0);\\n _removePrimaryPrice(token);\\n }\\n\\n minTimestamp = 0;\\n maxTimestamp = 0;\\n }\\n\\n // @dev get the length of tokensWithPrices\\n // @return the length of tokensWithPrices\\n function getTokensWithPricesCount() external view returns (uint256) {\\n return tokensWithPrices.length();\\n }\\n\\n // @dev get the tokens of tokensWithPrices for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the tokens of tokensWithPrices for the specified indexes\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {\\n return tokensWithPrices.valuesAt(start, end);\\n }\\n\\n // @dev get the primary price of a token\\n // @param token the token to get the price for\\n // @return the primary price of a token\\n function getPrimaryPrice(address token) external view returns (Price.Props memory) {\\n if (token == address(0)) { return Price.Props(0, 0); }\\n\\n Price.Props memory price = primaryPrices[token];\\n if (price.isEmpty()) {\\n revert Errors.EmptyPrimaryPrice(token);\\n }\\n\\n return price;\\n }\\n\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {\\n return _validatePrices(params, forAtomicAction);\\n }\\n\\n // @dev validate and set prices\\n // @param params OracleUtils.SetPricesParams\\n function _setPrices(\\n OracleUtils.ValidatedPrice[] memory prices\\n ) internal {\\n // in case of gasless relay the prices are not required if there is no need to swap fee tokens\\n if (prices.length == 0) {\\n return;\\n }\\n\\n if (tokensWithPrices.length() != 0) {\\n revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());\\n }\\n\\n uint256 _minTimestamp = prices[0].timestamp;\\n uint256 _maxTimestamp = prices[0].timestamp;\\n\\n for (uint256 i; i < prices.length; i++) {\\n OracleUtils.ValidatedPrice memory validatedPrice = prices[i];\\n\\n _setPrimaryPrice(validatedPrice.token, Price.Props(\\n validatedPrice.min,\\n validatedPrice.max\\n ));\\n\\n if (validatedPrice.timestamp < _minTimestamp) {\\n _minTimestamp = validatedPrice.timestamp;\\n }\\n\\n if (validatedPrice.timestamp > _maxTimestamp) {\\n _maxTimestamp = validatedPrice.timestamp;\\n }\\n\\n _emitOraclePriceUpdated(\\n validatedPrice.token,\\n validatedPrice.min,\\n validatedPrice.max,\\n validatedPrice.timestamp,\\n validatedPrice.provider\\n );\\n }\\n\\n uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);\\n if (_maxTimestamp - _minTimestamp > maxRange) {\\n revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);\\n }\\n\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n function _validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) internal returns (OracleUtils.ValidatedPrice[] memory) {\\n if (params.tokens.length != params.providers.length) {\\n revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);\\n }\\n\\n if (params.tokens.length != params.data.length) {\\n revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);\\n }\\n\\n OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);\\n\\n if (params.tokens.length == 0) {\\n return prices;\\n }\\n\\n uint256 maxPriceAge = forAtomicAction ? dataStore.getUint(Keys.MAX_ATOMIC_ORACLE_PRICE_AGE) : dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);\\n uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);\\n\\n for (uint256 i; i < params.tokens.length; i++) {\\n address _provider = params.providers[i];\\n IOracleProvider provider = IOracleProvider(_provider);\\n\\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(_provider))) {\\n revert Errors.InvalidOracleProvider(_provider);\\n }\\n\\n address token = params.tokens[i];\\n\\n bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(_provider));\\n\\n // if the action is atomic then only validate that the provider is an\\n // atomic provider\\n // else, validate that the provider matches the oracleProviderForToken\\n //\\n // since for atomic actions, any atomic provider can be used, it is\\n // recommended that only one atomic provider is configured per token\\n // otherwise there is a risk that if there is a difference in pricing\\n // between atomic oracle providers for a token, a user could use that\\n // to gain a profit by alternating actions between the two atomic\\n // providers\\n if (forAtomicAction) {\\n if (!isAtomicProvider) {\\n revert Errors.NonAtomicOracleProvider(_provider);\\n }\\n } else {\\n address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(address(this), token));\\n if (_provider != expectedProvider) {\\n revert Errors.InvalidOracleProviderForToken(_provider, expectedProvider);\\n }\\n }\\n\\n bytes memory data = params.data[i];\\n\\n OracleUtils.ValidatedPrice memory validatedPrice = provider.getOraclePrice(\\n token,\\n data\\n );\\n\\n // for atomic providers, the timestamp will be the current block's timestamp\\n // the timestamp should not be adjusted\\n if (provider.shouldAdjustTimestamp()) {\\n uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(_provider, token));\\n validatedPrice.timestamp -= timestampAdjustment;\\n }\\n\\n if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {\\n revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());\\n }\\n\\n if (!provider.isChainlinkOnChainProvider()) {\\n (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\\n\\n if (hasRefPrice) {\\n _validateRefPrice(\\n token,\\n validatedPrice.min,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n\\n _validateRefPrice(\\n token,\\n validatedPrice.max,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n prices[i] = validatedPrice;\\n }\\n\\n return prices;\\n }\\n\\n function _validateRefPrice(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n ) internal pure {\\n uint256 diff = Calc.diff(price, refPrice);\\n uint256 diffFactor = Precision.toFactor(diff, refPrice);\\n\\n if (diffFactor > maxRefPriceDeviationFactor) {\\n revert Errors.MaxRefPriceDeviationExceeded(\\n token,\\n price,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n function _setPrimaryPrice(address token, Price.Props memory price) internal {\\n if (price.min > price.max) {\\n revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);\\n }\\n\\n Price.Props memory existingPrice = primaryPrices[token];\\n\\n if (!existingPrice.isEmpty()) {\\n revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);\\n }\\n\\n primaryPrices[token] = price;\\n tokensWithPrices.add(token);\\n }\\n\\n function _removePrimaryPrice(address token) internal {\\n delete primaryPrices[token];\\n tokensWithPrices.remove(token);\\n }\\n\\n function _emitOraclePriceUpdated(\\n address token,\\n uint256 minPrice,\\n uint256 maxPrice,\\n uint256 timestamp,\\n address provider\\n ) internal {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"provider\\\", provider);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"minPrice\\\", minPrice);\\n eventData.uintItems.setItem(1, \\\"maxPrice\\\", maxPrice);\\n eventData.uintItems.setItem(2, \\\"timestamp\\\", timestamp);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OraclePriceUpdate\\\",\\n Cast.toBytes32(token),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x37cac3c6590c434acbf8b391b6a6fb875ecb671e2859f473d17d5afe7e1e38e5\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IOracle.sol\\\";\\n\\n// @title OracleModule\\n// @dev Provides convenience functions for interacting with the Oracle\\ncontract OracleModule {\\n IOracle public immutable oracle;\\n\\n constructor(IOracle _oracle) {\\n oracle = _oracle;\\n }\\n\\n // @dev sets oracle prices, perform any additional tasks required,\\n // and clear the oracle prices after\\n //\\n // care should be taken to avoid re-entrancy while using this call\\n // since re-entrancy could allow functions to be called with prices\\n // meant for a different type of transaction\\n // the tokensWithPrices.length check in oracle.setPrices should help\\n // mitigate this\\n //\\n // @param params OracleUtils.SetPricesParams\\n modifier withOraclePrices(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPrices(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n modifier withOraclePricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPricesForAtomicAction(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n // @dev set oracle prices for a simulation\\n // tokensWithPrices is not set in this function\\n // it is possible for withSimulatedOraclePrices to be called and a function\\n // using withOraclePrices to be called after\\n // or for a function using withOraclePrices to be called and withSimulatedOraclePrices\\n // called after\\n // this should not cause an issue because this transaction should always revert\\n // and any state changes based on simulated prices as well as the setting of simulated\\n // prices should not be persisted\\n // @param params OracleUtils.SimulatePricesParams\\n modifier withSimulatedOraclePrices(\\n OracleUtils.SimulatePricesParams memory params\\n ) {\\n if (params.primaryTokens.length != params.primaryPrices.length) {\\n revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);\\n }\\n\\n for (uint256 i; i < params.primaryTokens.length; i++) {\\n address token = params.primaryTokens[i];\\n Price.Props memory price = params.primaryPrices[i];\\n oracle.setPrimaryPrice(token, price);\\n }\\n\\n oracle.setTimestamps(params.minTimestamp, params.maxTimestamp);\\n\\n _;\\n\\n revert Errors.EndOfOracleSimulation();\\n }\\n}\\n\",\"keccak256\":\"0x19e4098e3f037bb6e1deb3a93aa98d42ceac46bf10553fb9aff784f9fbbc16ff\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\n// @title OracleStore\\n// @dev Stores the list of oracle signers\\ncontract OracleStore is RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n EventEmitter public immutable eventEmitter;\\n\\n EnumerableSet.AddressSet internal signers;\\n\\n constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {\\n eventEmitter = _eventEmitter;\\n }\\n\\n // @dev adds a signer\\n // @param account address of the signer to add\\n function addSigner(address account) external onlyController {\\n signers.add(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerAdded\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev removes a signer\\n // @param account address of the signer to remove\\n function removeSigner(address account) external onlyController {\\n signers.remove(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerRemoved\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev get the total number of signers\\n // @return the total number of signers\\n function getSignerCount() external view returns (uint256) {\\n return signers.length();\\n }\\n\\n // @dev get the signer at the specified index\\n // @param index the index of the signer to get\\n // @return the signer at the specified index\\n function getSigner(uint256 index) external view returns (address) {\\n return signers.at(index);\\n }\\n\\n // @dev get the signers for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the signers for the specified indexes\\n function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {\\n return signers.valuesAt(start, end);\\n }\\n}\\n\",\"keccak256\":\"0x5b9c2917e29aa696a8385f9f8b6a0cd0f1ef9a0b08d8096a2f19367e89cc09e7\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n // @dev IsPositionLiquidatableCache struct used in isPositionLiquidatable\\n // to avoid stack too deep errors\\n // @param positionPnlUsd the position's pnl in USD\\n // @param minCollateralFactor the min collateral factor\\n // @param collateralTokenPrice the collateral token price\\n // @param collateralUsd the position's collateral in USD\\n // @param usdDeltaForPriceImpact the usdDelta value for the price impact calculation\\n // @param priceImpactUsd the price impact of closing the position in USD\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n // @dev check if a position is liquidatable\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0x98416c7f41b0baf01552655c8034e98c71f204b6449fa967c44eb2df84391fab\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n}\\n\",\"keccak256\":\"0x9c3e0a72f1813ac5d81fa53198fa6f78ca3251485b5f2053c86c91d71b7f4f58\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa69173dc70bac74d03562b0abf2fee9eb7802cd94fd0d56d289fd7f1930054b7\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/BasicMulticall.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/ErrorUtils.sol\\\";\\n\\n/**\\n * @title BasicMulticall\\n */\\nabstract contract BasicMulticall {\\n /**\\n * @dev Receives and executes a batch of function calls on this contract.\\n */\\n function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n\\n for (uint256 i; i < data.length; i++) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n ErrorUtils.revertWithParsedMessage(result);\\n }\\n\\n results[i] = result;\\n }\\n\\n return results;\\n }\\n}\\n\",\"keccak256\":\"0xdf9d58a9b7d7b28be24bd2668da62ca377f6e1aa1e65111fd6da7cc6b5db1851\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Uint256Mask.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary Uint256Mask {\\n struct Mask {\\n uint256 bits;\\n }\\n\\n function validateUniqueAndSetIndex(\\n Mask memory mask,\\n uint256 index,\\n string memory label\\n ) internal pure {\\n if (index >= 256) {\\n revert Errors.MaskIndexOutOfBounds(index, label);\\n }\\n\\n uint256 bit = 1 << index;\\n\\n if (mask.bits & bit != 0) {\\n revert Errors.DuplicatedIndex(index, label);\\n }\\n\\n mask.bits = mask.bits | bit;\\n }\\n}\\n\",\"keccak256\":\"0x96aaf43efa3a092b2d8d1e88addab6c31f5a7f526b84a290b9ba43e803592e01\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051615cea380380615cea83398101604081905261003091610071565b6001600160a01b0391821660805293811660a05291821660e0528116610100521660c0526100e6565b6001600160a01b038116811461006e57600080fd5b50565b600080600080600060a0868803121561008957600080fd5b855161009481610059565b60208701519095506100a581610059565b60408701519094506100b681610059565b60608701519093506100c781610059565b60808701519092506100d881610059565b809150509295509295909350565b60805160a05160c05160e05161010051615a006102ea600039600081816101df015281816120e4015261305a015260008181610260015281816107d20152818161099f015281816109f3015281816111de015281816112320152818161128601528181611a5f01528181611ab301528181611b0701528181611b5b0152818161293601528181612b8c015281816132d101526135900152600081816103fe0152818161064e015281816107a3015281816107f801528181610b5c01528181610b9001528181610dad01528181610f2601528181610f5b0152818161145401528181611488015281816116e001528181611754015281816118700152818161189f015281816118c501528181611d8e01528181611dc2015281816120b50152818161210a015281816122be0152818161231301528181612577015281816125a6015281816125cc015281816129070152818161295c01528181612b5d01528181612bb201528181612dc301528181612e180152818161302b01528181613080015281816132a2015281816132f70152818161345f01528181613561015281816135b60152818161381f0152818161384e0152818161387401528181613a760152613b0f0152600081816102f901528181613e3a0152613eb8015260008181610213015281816104c7015281816122ed01528181612df20152613bb00152615a006000f3fe608060405234801561001057600080fd5b506004361061016a5760003560e01c8063208dd1ff1461016f5780632a083ca3146101845780632ab148dd146101a1578063314907c1146101b457806331847c96146101c7578063392bf7f6146101da5780634a4a7b041461020e5780635588ec5a14610235578063569936a414610248578063660d0d671461025b5780636d00753e14610282578063781cc3d31461029557806378b79025146102a85780637ed67107146102bb578063881be502146102ce578063990200cb146102e15780639ff78c30146102f4578063a6a58fab1461031b578063ac9650d81461032e578063ad4e4ab21461034e578063b5256f3814610361578063b971779414610374578063cd63bfa514610387578063cdb07a4f1461039a578063d0b91b01146103ad578063d597d570146103c0578063db477adc146103d3578063e38335e5146103e6578063f3388e75146103f9578063feca03a514610420575b600080fd5b61018261017d36600461453d565b610433565b005b61018e6206978081565b6040519081526020015b60405180910390f35b6101826101af3660046145af565b6105e3565b6101826101c2366004614613565b6106c7565b6101826101d5366004614646565b61094a565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b6040516101989190614688565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b61018261024336600461469c565b610d84565b610182610256366004614732565b610e29565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b610182610290366004614791565b611152565b6101826102a33660046147db565b6116b8565b6101826102b63660046147f4565b611740565b6101826102c9366004614820565b611a28565b6101826102dc366004614613565b612029565b6101826102ef36600461487e565b612259565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b6101826103293660046148b7565b6124a1565b61034161033c366004614948565b612783565b6040516101989190614a35565b61018261035c366004614a60565b612896565b61018261036f366004614aa4565b612aef565b61018261038236600461487e565b612d5e565b610182610395366004614613565b612f9f565b6101826103a8366004614613565b6131cc565b61018e6103bb366004614af9565b613445565b6101826103ce366004614a60565b6134f0565b6101826103e13660046148b7565b613749565b6101826103f4366004614af9565b613a4d565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b61018e61042e3660046145af565b613af5565b6104b060405160200161046b9060208082526011908201527054494d454c4f434b5f4d554c544953494760781b604082015260600190565b604051602081830303815290604052805190602001206040518060400160405280601181526020017054494d454c4f434b5f4d554c544953494760781b815250613b99565b60405163208dd1ff60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063208dd1ff906104fe9085908590600401614bab565b600060405180830381600087803b15801561051857600080fd5b505af115801561052c573d6000803e3d6000fd5b50505050610538614430565b8051610545906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516105729160009086613cb2565b6080810151610582906001613c4d565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516105b29160009085613d0f565b6105de6040518060400160405280600a8152602001695265766f6b65526f6c6560b01b81525082613d62565b505050565b6106376040516020016105f590614bc4565b604051602081830303815290604052805190602001206040518060400160405280600e81526020016d2a24a6a2a627a1a5afa0a226a4a760911b815250613b99565b60405163134008d360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063134008d39061068e9088906000908990899089908990600401614c15565b600060405180830381600087803b1580156106a857600080fd5b505af11580156106bc573d6000803e3d6000fd5b505050505050505050565b6106d96040516020016105f590614bc4565b6001600160a01b03831661070b578260405163cb9339d560e01b81526004016107029190614688565b60405180910390fd5b600060405160200161073d906020808252600c908201526b2322a2afa922a1a2a4ab22a960a11b604082015260600190565b6040516020818303038152906040528051906020012084604051602401610765929190614c52565b60405160208183030381529060405263ca446dd960e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015610854573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108789190614c69565b6040518763ffffffff1660e01b815260040161089996959493929190614c82565b600060405180830381600087803b1580156108b357600080fd5b505af11580156108c7573d6000803e3d6000fd5b505050506108d3614430565b80516108e0906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161090d9160009088613cb2565b6109436040518060400160405280601481526020017329b4b3b730b629b2ba2332b2a932b1b2b4bb32b960611b81525082613d62565b5050505050565b61095c6040516020016105f590614bc4565b8361097c57846040516318b900b360e21b81526004016107029190614688565b6040805160028082526060820183526000926020830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106109d1576109d1614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110610a2557610a25614cdd565b6001600160a01b03929092166020928302919091019091015260408051600280825260608201909252600091816020015b6060815260200190600190039081610a56579050509050610a7687613f1f565b86604051602401610a88929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b17905281518290600090610ac557610ac5614cdd565b6020026020010181905250610ad987613f9d565b85604051602401610aeb929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110610b2a57610b2a614cdd565b6020908102919091010152604080516002808252606082019092526000918160200160208202803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb084838589897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c109190614c69565b6040518763ffffffff1660e01b8152600401610c3196959493929190614d78565b600060405180830381600087803b158015610c4b57600080fd5b505af1158015610c5f573d6000803e3d6000fd5b50505050610c6b614430565b8051610c78906001613c4d565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610ca3916000908c613cb2565b6080810151610cb3906001613c4d565b60408051808201909152601081526f195919d951185d1854dd1c99585b525960821b60208201526080820151610cec916000908b613d0f565b6020810151610cfc906001613c4d565b610d4b60006040518060400160405280601b81526020017a656467654461746153747265616d546f6b656e446563696d616c7360281b815250898460200151613d0f909392919063ffffffff16565b6106bc604051806040016040528060178152602001765369676e616c536574456467654461746153747265616d60481b81525082613d62565b610d966040516020016105f590614bc4565b60405163d0663e6160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d0663e6190610def9089906000908a908a908a908a908a90600401614ee8565b600060405180830381600087803b158015610e0957600080fd5b505af1158015610e1d573d6000803e3d6000fd5b50505050505050505050565b610e3b6040516020016105f590614bc4565b6001600160a01b038616610e6257604051634e6e36d560e11b815260040160405180910390fd5b6001600160a01b038516610e895760405163066f53b160e01b815260040160405180910390fd5b6001600160a01b038416610eb05760405163d551823d60e01b815260040160405180910390fd5b82600003610ed1576040516301d6f7b160e01b815260040160405180910390fd5b6000858585604051602401610ee893929190614f98565b604051602081830303815290604052632f1a9acf60e11b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a8860008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb9190614c69565b6040518763ffffffff1660e01b8152600401610ffc96959493929190614c82565b600060405180830381600087803b15801561101657600080fd5b505af115801561102a573d6000803e3d6000fd5b50505050611036614430565b8051611043906003613c4d565b6040805180820190915260068152651d185c99d95d60d21b6020820152815161106f916000908b613cb2565b6040805180820190915260058152643a37b5b2b760d91b6020820152815161109a916001908a613cb2565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516110c89160019089613cb2565b60208101516110d8906001613c4d565b611112600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151613d0f909392919063ffffffff16565b611148604051806040016040528060148152602001735369676e616c5769746864726177546f6b656e7360601b81525082613d62565b5050505050505050565b6111646040516020016105f590614bc4565b68327cb2734119d3b7a9601e1b8311156111b95760405160200161118790614fbc565b6040516020818303038152906040528051906020012083604051635ebb87c960e01b8152600401610702929190614cf3565b60408051600380825260808201909252600091602082016060803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061121057611210614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160018151811061126457611264614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816002815181106112b8576112b8614cdd565b6001600160a01b03929092166020928302919091019091015260408051600380825260808201909252600091816020015b60608152602001906001900390816112e957905050905061130988613fe0565b8760405160240161131b929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b1790528151829060009061135857611358614cdd565b602002602001018190525061136c88614014565b8660405160240161137e929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b1790528151829060019081106113bd576113bd614cdd565b60200260200101819052506113d188614050565b856040516024016113e3929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b17905281518290600290811061142257611422614cdd565b6020908102919091010152604080516003808252608082019092526000918160200160208202803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb084838589897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115089190614c69565b6040518763ffffffff1660e01b815260040161152996959493929190614d78565b600060405180830381600087803b15801561154357600080fd5b505af1158015611557573d6000803e3d6000fd5b50505050611563614430565b8051611570906001613c4d565b6040805180820190915260058152643a37b5b2b760d91b6020820152815161159b916000908d613cb2565b60808101516115ab906001613c4d565b60408051808201909152600681526519995959125960d21b602082015260808201516115da916000908c613d0f565b60208101516115ea906002613c4d565b6116326000604051806040016040528060148152602001733230ba30a9ba3932b0b6a6bab63a34b83634b2b960611b8152508a8460200151613d0f909392919063ffffffff16565b61168360016040518060400160405280601f81526020017f6461746153747265616d537072656164526564756374696f6e466163746f7200815250898460200151613d0f909392919063ffffffff16565b610e1d604051806040016040528060138152602001725369676e616c5365744461746153747265616d60681b81525082613d62565b6116ca6040516020016105f590614bc4565b60405163c4d252f560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c4d252f590602401600060405180830381600087803b15801561172c57600080fd5b505af1158015610943573d6000803e3d6000fd5b6117526040516020016105f590614bc4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d49190614c69565b83116117f6576040516373586edb60e11b815260048101849052602401610702565b6206978083111561181d57604051633ebd9bc360e21b815260048101849052602401610702565b60008360405160240161183291815260200190565b6040516020818303038152906040526364d6235360e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119459190614c69565b6040518763ffffffff1660e01b815260040161196696959493929190614c82565b600060405180830381600087803b15801561198057600080fd5b505af1158015611994573d6000803e3d6000fd5b505050506119a0614430565b60208101516119b0906001613c4d565b6119f160006040518060400160405280600d81526020016c74696d656c6f636b44656c617960981b815250878460200151613d0f909392919063ffffffff16565b61094360405180604001604052806015815260200174496e63726561736554696d656c6f636b44656c617960581b81525082613d62565b611a3a6040516020016105f590614bc4565b60408051600480825260a08201909252600091602082016080803683370190505090507f000000000000000000000000000000000000000000000000000000000000000081600081518110611a9157611a91614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611ae557611ae5614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600281518110611b3957611b39614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600381518110611b8d57611b8d614cdd565b6001600160a01b03929092166020928302919091019091015260408051600480825260a08201909252600091816020015b6060815260200190600190039081611bbe579050509050611bde89614061565b88604051602401611bf0929190614c52565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905281518290600090611c2d57611c2d614cdd565b6020026020010181905250611c4189614091565b87604051602401611c53929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110611c9257611c92614cdd565b6020026020010181905250611ca6896140cc565b86604051602401611cb8929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906002908110611cf757611cf7614cdd565b6020026020010181905250611d0b8961410f565b85604051602401611d1d929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906003908110611d5c57611d5c614cdd565b602090810291909101015260408051600480825260a082019092526000918160200160208202803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb084838589897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e429190614c69565b6040518763ffffffff1660e01b8152600401611e6396959493929190614d78565b600060405180830381600087803b158015611e7d57600080fd5b505af1158015611e91573d6000803e3d6000fd5b50505050611e9d614430565b8051611eaa906002613c4d565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611ed5916000908e613cb2565b6040805180820190915260098152681c1c9a58d95199595960ba1b60208201528151611f04916001908d613cb2565b6020810151611f14906003613c4d565b611f5b600060405180604001604052806013815260200172383934b1b2a332b2b226bab63a34b83634b2b960691b8152508b8460200151613d0f909392919063ffffffff16565b611fa960016040518060400160405280601a815260200179383934b1b2a332b2b22432b0b93a3132b0ba223ab930ba34b7b760311b8152508a8460200151613d0f909392919063ffffffff16565b611fe860026040518060400160405280600b81526020016a737461626c65507269636560a81b815250898460200151613d0f909392919063ffffffff16565b61201c6040518060400160405280601281526020017114da59db985b14d95d141c9a58d95199595960721b81525082613d62565b5050505050505050505050565b61203b6040516020016105f590614bc4565b6001600160a01b038316612064578260405163c1b14c9160e01b81526004016107029190614688565b6000836040516024016120779190614688565b604051602081830303815290604052630e316ab760e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612166573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218a9190614c69565b6040518763ffffffff1660e01b81526004016121ab96959493929190614c82565b600060405180830381600087803b1580156121c557600080fd5b505af11580156121d9573d6000803e3d6000fd5b505050506121e5614430565b80516121f2906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161221f9160009088613cb2565b6109436040518060400160405280601881526020017729b4b3b730b62932b6b7bb32a7b930b1b632a9b4b3b732b960411b81525082613d62565b61226b6040516020016105f590614bc4565b60008484604051602401612280929190614bab565b604051602081830303815290604052632ac9d0b760e21b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa15801561236f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123939190614c69565b6040518763ffffffff1660e01b81526004016123b496959493929190614c82565b600060405180830381600087803b1580156123ce57600080fd5b505af11580156123e2573d6000803e3d6000fd5b505050506123ee614430565b80516123fb906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516124289160009089613cb2565b6080810151612438906001613c4d565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516124689160009088613d0f565b6124996040518060400160405280600f81526020016e5369676e616c4772616e74526f6c6560881b81525082613d62565b505050505050565b6124b36040516020016105f590614bc4565b6001600160a01b0385166124da576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b0384166125015760405163d551823d60e01b815260040160405180910390fd5b8260000361252257604051630d1bbc9560e01b815260040160405180910390fd5b600085858560405160240161253993929190614f98565b604051602081830303815290604052632bae9a3560e11b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612628573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264c9190614c69565b6040518763ffffffff1660e01b815260040161266d96959493929190614c82565b600060405180830381600087803b15801561268757600080fd5b505af115801561269b573d6000803e3d6000fd5b505050506126a7614430565b80516126b4906002613c4d565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126e0916000908a613cb2565b6040805180820190915260088152673932b1b2b4bb32b960c11b6020820152815161270e9160019089613cb2565b602081015161271e906001613c4d565b612758600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151613d0f909392919063ffffffff16565b61277a6040518060600160405280602481526020016159a76024913982613d62565b50505050505050565b6060816001600160401b0381111561279d5761279d614cc7565b6040519080825280602002602001820160405280156127d057816020015b60608152602001906001900390816127bb5790505b50905060005b8281101561288f57600080308686858181106127f4576127f4614cdd565b90506020028101906128069190614fff565b604051612814929190615045565b600060405180830381855af49150503d806000811461284f576040519150601f19603f3d011682016040523d82523d6000602084013e612854565b606091505b5091509150816128675761286781614141565b8084848151811061287a5761287a614cdd565b602090810291909101015250506001016127d6565b5092915050565b6128a86040516020016105f590614bc4565b60006128b38561417a565b6040516024810191909152841515604482015260640160405160208183030381529060405263abfdcced60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129dc9190614c69565b6040518763ffffffff1660e01b81526004016129fd96959493929190614c82565b600060405180830381600087803b158015612a1757600080fd5b505af1158015612a2b573d6000803e3d6000fd5b50505050612a37614430565b8051612a44906001613c4d565b604080518082019091526008815267383937bb34b232b960c11b60208201528151612a729160009089613cb2565b6060810151612a82906001613c4d565b60408051808201909152600581526476616c756560d81b60208201526060820151612ab091600090886141b9565b6124996040518060400160405280601d81526020017f5369676e616c53657441746f6d69634f7261636c6550726f766964657200000081525082613d62565b612b016040516020016105f590614bc4565b6000612b0d868661420e565b84604051602401612b1f929190614c52565b60405160208183030381529060405263ca446dd960e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c329190614c69565b6040518763ffffffff1660e01b8152600401612c5396959493929190614c82565b600060405180830381600087803b158015612c6d57600080fd5b505af1158015612c81573d6000803e3d6000fd5b50505050612c8d614430565b8051612c9a906003613c4d565b6040805180820190915260068152656f7261636c6560d01b60208201528151612cc6916000908a613cb2565b6040805180820190915260058152643a37b5b2b760d91b60208201528151612cf19160019089613cb2565b604080518082019091526008815267383937bb34b232b960c11b60208201528151612d1f9160029088613cb2565b61277a6040518060400160405280601f81526020017f5369676e616c5365744f7261636c6550726f7669646572466f72546f6b656e0081525082613d62565b612d706040516020016105f590614bc4565b60008484604051602401612d85929190614bab565b60405160208183030381529060405263208dd1ff60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e989190614c69565b6040518763ffffffff1660e01b8152600401612eb996959493929190614c82565b600060405180830381600087803b158015612ed357600080fd5b505af1158015612ee7573d6000803e3d6000fd5b50505050612ef3614430565b8051612f00906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151612f2d9160009089613cb2565b6080810151612f3d906001613c4d565b604080518082019091526007815266726f6c654b657960c81b60208201526080820151612f6d9160009088613d0f565b6124996040518060400160405280601081526020016f5369676e616c5265766f6b65526f6c6560801b81525082613d62565b612fb16040516020016105f590614bc4565b6001600160a01b038316612fda578260405163c1b14c9160e01b81526004016107029190614688565b600083604051602401612fed9190614688565b6040516020818303038152906040526375896b0f60e11b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131009190614c69565b6040518763ffffffff1660e01b815260040161312196959493929190614c82565b600060405180830381600087803b15801561313b57600080fd5b505af115801561314f573d6000803e3d6000fd5b5050505061315b614430565b8051613168906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516131959160009088613cb2565b6109436040518060400160405280601581526020017429b4b3b730b620b23227b930b1b632a9b4b3b732b960591b81525082613d62565b6131de6040516020016105f590614bc4565b6001600160a01b0383166132075782604051630f773b1f60e31b81526004016107029190614688565b600060405160200161323c906020808252600f908201526e484f4c44494e475f4144445245535360881b604082015260600190565b6040516020818303038152906040528051906020012084604051602401613264929190614c52565b60405160208183030381529060405263ca446dd960e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133779190614c69565b6040518763ffffffff1660e01b815260040161339896959493929190614c82565b600060405180830381600087803b1580156133b257600080fd5b505af11580156133c6573d6000803e3d6000fd5b505050506133d2614430565b80516133df906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161340c9160009088613cb2565b610943604051806040016040528060178152602001765369676e616c536574486f6c64696e674164647265737360481b81525082613d62565b60405163b1c5f42760e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b1c5f427906134a2908c908c908a908a908e908e908c908c90600401615055565b602060405180830381865afa1580156134bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e39190614c69565b9998505050505050505050565b6135026040516020016105f590614bc4565b600061350d856142a3565b6040516024810191909152841515604482015260640160405160208183030381529060405263abfdcced60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613612573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136369190614c69565b6040518763ffffffff1660e01b815260040161365796959493929190614c82565b600060405180830381600087803b15801561367157600080fd5b505af1158015613685573d6000803e3d6000fd5b50505050613691614430565b805161369e906001613c4d565b604080518082019091526008815267383937bb34b232b960c11b602082015281516136cc9160009089613cb2565b60608101516136dc906001613c4d565b60408051808201909152600581526476616c756560d81b6020820152606082015161370a91600090886141b9565b6124996040518060400160405280601e81526020017f5369676e616c5365744f7261636c6550726f7669646572456e61626c6564000081525082613d62565b61375b6040516020016105f590614bc4565b6001600160a01b038516613782576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b0384166137a957604051639ab5d12760e01b815260040160405180910390fd5b826000036137ca5760405163b3d3553960e01b815260040160405180910390fd5b60008585856040516024016137e193929190614f98565b60405160208183030381529060405263f128024b60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f49190614c69565b6040518763ffffffff1660e01b815260040161391596959493929190614c82565b600060405180830381600087803b15801561392f57600080fd5b505af1158015613943573d6000803e3d6000fd5b5050505061394f614430565b805161395c906002613c4d565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151613988916000908a613cb2565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b602082015281516139bc9160019089613cb2565b60208101516139cc906001613c4d565b613a0f60006040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250878460200151613d0f909392919063ffffffff16565b61277a6040518060400160405280601c81526020017b14da59db985b1499591d58d953195b9d125b5c1858dd105b5bdd5b9d60221b81525082613d62565b613a5f6040516020016105f590614bc4565b60405163e38335e560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e38335e590613ab9908b908b908b908b908b908b908b908b90600401615055565b600060405180830381600087803b158015613ad357600080fd5b505af1158015613ae7573d6000803e3d6000fd5b505050505050505050505050565b604051638065657f60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638065657f90613b4e90899085908a908a908a908a90600401614c15565b602060405180830381865afa158015613b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8f9190614c69565b9695505050505050565b60405163ac4ab3fb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac4ab3fb90613be79033908690600401614bab565b602060405180830381865afa158015613c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2891906150c6565b613c4957338160405163a35b150b60e01b81526004016107029291906150e3565b5050565b806001600160401b03811115613c6557613c65614cc7565b604051908082528060200260200182016040528015613cab57816020015b604080518082019091526060815260006020820152815260200190600190039081613c835790505b5090915250565b8184600001518481518110613cc957613cc9614cdd565b6020026020010151600001819052508084600001518481518110613cef57613cef614cdd565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110613d2657613d26614cdd565b6020026020010151600001819052508084600001518481518110613d4c57613d4c614cdd565b6020026020010151602001818152505050505050565b613d6a614430565b600083604051602001613d7d919061510f565b604051602081830303815290604052805190602001209050613dad60018360800151613c4d90919063ffffffff16565b604080518082019091526009815268616374696f6e4b657960b81b60208201526080830151613ddf9160009084613d0f565b60c0820151613def9060016142e3565b60408051808201909152600b81526a1858dd1a5bdb931858995b60aa1b602082015260c0830151613e239160009087614345565b604051630937807960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906324de01e490613e719084908690600401615895565b600060405180830381600087803b158015613e8b57600080fd5b505af1158015613e9f573d6000803e3d6000fd5b505060405163483624fb60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063906c49f69150613ef190879087906004016158d8565b600060405180830381600087803b158015613f0b57600080fd5b505af1158015611148573d6000803e3d6000fd5b6000604051602001613f5890602080825260139082015272115111d157d110551057d4d51491505357d251606a1b604082015260600190565b6040516020818303038152906040528051906020012082604051602001613f80929190614c52565b604051602081830303815290604052805190602001209050919050565b6000604051602001613f58906020808252601f908201527f454447455f444154415f53545245414d5f544f4b454e5f444543494d414c5300604082015260600190565b6000604051602001613f58906020808252600e908201526d1110551057d4d51491505357d25160921b604082015260600190565b6000604051602001613f58906020808252601690820152752220aa20afa9aa2922a0a6afa6aaa62a24a82624a2a960511b604082015260600190565b6000604051602001613f5890614fbc565b6000604051602001613f58906020808252600a908201526914149250d157d191515160b21b604082015260600190565b6000604051602001613f5890602080825260159082015274282924a1a2afa322a2a22fa6aaa62a24a82624a2a960591b604082015260600190565b6000604051602001613f58906020808252601d908201527f50524943455f464545445f4845415254424541545f4455524154494f4e000000604082015260600190565b6000604051602001613f58906020808252600c908201526b535441424c455f505249434560a01b604082015260600190565b60008061414d83614397565b915091508015614171578160405162461bcd60e51b8152600401610702919061510f565b6105de83614427565b6000604051602001613f589060208082526019908201527824a9afa0aa27a6a4a1afa7a920a1a622afa82927ab24a222a960391b604082015260600190565b81846000015184815181106141d0576141d0614cdd565b60200260200101516000018190525080846000015184815181106141f6576141f6614cdd565b60209081029190910181015191151591015250505050565b600060405160200161424d9060208082526019908201527827a920a1a622afa82927ab24a222a92fa327a92faa27a5a2a760391b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800160405160208183030381529060405280519060200120905092915050565b6000604051602001613f58906020808252601a90820152791254d7d3d49050d31157d41493d59251115497d153905093115160321b604082015260600190565b806001600160401b038111156142fb576142fb614cc7565b604051908082528060200260200182016040528015613cab57816020015b604080518082019091526060808252602082015281526020019060019003908161431957505090915250565b818460000151848151811061435c5761435c614cdd565b602002602001015160000181905250808460000151848151811061438257614382614cdd565b60200260200101516020018190525050505050565b606060006044835110156143be575050604080516020810190915260008082529092909150565b60006143cb846020015190565b90506307b9e43360e51b6001600160e01b031982160161440a57600484019350838060200190518101906143ff91906158fd565b946001945092505050565b600060405180602001604052806000815250909250925050915091565b80518060208301fd5b604080516101208101909152606060e0820181815261010083019190915281908152602001614472604051806040016040528060608152602001606081525090565b8152602001614494604051806040016040528060608152602001606081525090565b81526020016144b6604051806040016040528060608152602001606081525090565b81526020016144d8604051806040016040528060608152602001606081525090565b81526020016144fa604051806040016040528060608152602001606081525090565b815260200161451c604051806040016040528060608152602001606081525090565b905290565b80356001600160a01b038116811461453857600080fd5b919050565b6000806040838503121561455057600080fd5b61455983614521565b946020939093013593505050565b60008083601f84011261457957600080fd5b5081356001600160401b0381111561459057600080fd5b6020830191508360208285010111156145a857600080fd5b9250929050565b6000806000806000608086880312156145c757600080fd5b6145d086614521565b945060208601356001600160401b038111156145eb57600080fd5b6145f788828901614567565b9699909850959660408101359660609091013595509350505050565b60008060006060848603121561462857600080fd5b61463184614521565b95602085013595506040909401359392505050565b600080600080600060a0868803121561465e57600080fd5b61466786614521565b97602087013597506040870135966060810135965060800135945092505050565b6001600160a01b0391909116815260200190565b60008060008060008060a087890312156146b557600080fd5b6146be87614521565b955060208701356001600160401b038111156146d957600080fd5b6146e589828a01614567565b909650945050604087013592506060870135915060808701356001600160401b0381111561471257600080fd5b87016060818a03121561472457600080fd5b809150509295509295509295565b60008060008060008060c0878903121561474b57600080fd5b61475487614521565b955061476260208801614521565b945061477060408801614521565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008060008060c087890312156147aa57600080fd5b6147b387614521565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b6000602082840312156147ed57600080fd5b5035919050565b60008060006060848603121561480957600080fd5b505081359360208301359350604090920135919050565b600080600080600080600060e0888a03121561483b57600080fd5b61484488614521565b965061485260208901614521565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b6000806000806080858703121561489457600080fd5b61489d85614521565b966020860135965060408601359560600135945092505050565b600080600080600060a086880312156148cf57600080fd5b6148d886614521565b94506148e660208701614521565b94979496505050506040830135926060810135926080909101359150565b60008083601f84011261491657600080fd5b5081356001600160401b0381111561492d57600080fd5b6020830191508360208260051b85010111156145a857600080fd5b6000806020838503121561495b57600080fd5b82356001600160401b0381111561497157600080fd5b61497d85828601614904565b90969095509350505050565b60005b838110156149a457818101518382015260200161498c565b50506000910152565b600081518084526149c5816020860160208601614989565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852614a138383516149ad565b60209889019890935091909101906001016149f7565b50909695505050505050565b602081526000614a4860208301846149d9565b9392505050565b8015158114614a5d57600080fd5b50565b60008060008060808587031215614a7657600080fd5b614a7f85614521565b93506020850135614a8f81614a4f565b93969395505050506040820135916060013590565b600080600080600060a08688031215614abc57600080fd5b614ac586614521565b9450614ad360208701614521565b9350614ae160408701614521565b94979396509394606081013594506080013592915050565b60008060008060008060008060a0898b031215614b1557600080fd5b88356001600160401b03811115614b2b57600080fd5b614b378b828c01614904565b90995097505060208901356001600160401b03811115614b5657600080fd5b614b628b828c01614904565b90975095505060408901356001600160401b03811115614b8157600080fd5b614b8d8b828c01614904565b999c989b509699959896976060870135966080013595509350505050565b6001600160a01b03929092168252602082015260400190565b6020808252600e908201526d2a24a6a2a627a1a5afa0a226a4a760911b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201526000614c3d60a083018688614bec565b60608301949094525060800152949350505050565b9182526001600160a01b0316602082015260400190565b600060208284031215614c7b57600080fd5b5051919050565b60018060a01b038716815285602082015260c060408201526000614ca960c08301876149ad565b606083019590955250608081019290925260a0909101529392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b918252602082015260400190565b600081518084526020840193506020830160005b82811015614d3c5781516001600160a01b0316865260209586019590910190600101614d15565b5093949350505050565b600081518084526020840193506020830160005b82811015614d3c578151865260209586019590910190600101614d5a565b60c081526000614d8b60c0830189614d01565b8281036020840152614d9d8189614d46565b90508281036040840152614db181886149d9565b60608401969096525050608081019290925260a0909101529392505050565b6000808335601e19843603018112614de757600080fd5b83016020810192503590506001600160401b03811115614e0657600080fd5b8060051b36038213156145a857600080fd5b81835260208301925060008160005b84811015614d3c576001600160a01b03614e4083614521565b1686526020958601959190910190600101614e27565b60008383855260208501945060208460051b8201018360005b86811015614a2957838303601f19018852600080833536899003601e19018112614e97578283fd5b88016020810192503590506001600160401b03811115614eb657600080fd5b803603821315614ec557600080fd5b614ed0858284614bec565b60209a8b019a90955093909301925050600101614e6f565b60018060a01b038816815286602082015260c060408201526000614f1060c083018789614bec565b85606084015284608084015282810360a0840152614f2e8485614dd0565b60608352614f40606084018284614e18565b915050614f506020860186614dd0565b8383036020850152614f63838284614e18565b92505050614f746040860186614dd0565b8383036040850152614f87838284614e56565b9d9c50505050505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526023908201527f444154415f53545245414d5f5350524541445f524544554354494f4e5f4641436040820152622a27a960e91b606082015260800190565b6000808335601e1984360301811261501657600080fd5b8301803591506001600160401b0382111561503057600080fd5b6020019150368190038213156145a857600080fd5b8183823760009101908152919050565b60a08152600061506960a083018a8c614e18565b82810360208401528781526001600160fb1b0388111561508857600080fd5b8760051b808a602084013701828103602090810160408501526150ae9082018789614e56565b60608401959095525050608001529695505050505050565b6000602082840312156150d857600080fd5b8151614a4881614a4f565b6001600160a01b0383168152604060208201819052600090615107908301846149ad565b949350505050565b602081526000614a4860208301846149ad565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261516660408601826149ad565b90506020820151915084810360208601526151818183614d01565b60209a8b019a90955093909301925050600101615140565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561521357605f1988860301835283518051604087526151eb60408801826149ad565b6020928301516001600160a01b031697830197909752509384019392909201916001016151c5565b505050506020830151848203602086015261522e8282615122565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261527b60408601826149ad565b90506020820151915084810360208601526152968183614d46565b60209a8b019a90955093909301925050600101615255565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561531f57605f19888603018352835180516040875261530060408801826149ad565b60209283015197830197909752509384019392909201916001016152da565b505050506020830151848203602086015261522e8282615237565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261537e60408601826149ad565b6020928301518682038785015280518083529084019360009350909101905b808310156153c0578351825260208201915060208401935060018301925061539d565b5060209a8b019a90955093909301925050600101615358565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561544a57605f19888603018352835180516040875261542b60408801826149ad565b6020928301519783019790975250938401939290920191600101615405565b505050506020830151848203602086015261522e828261533a565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f1985840301885281518051604085526154a960408601826149ad565b6020928301518682038785015280518083529084019360009350909101905b808310156154ed578351151582526020820191506020840193506001830192506154c8565b5060209a8b019a90955093909301925050600101615483565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561557957605f19888603018352835180516040875261555860408801826149ad565b60209283015115159783019790975250938401939290920191600101615532565b505050506020830151848203602086015261522e8282615465565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561544a57605f1988860301835283518051604087526155e660408801826149ad565b60209283015197830197909752509384019392909201916001016155c0565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261564960408601826149ad565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b828110156156a257601f1985830301845261568d8287516149ad565b60209687019694909401939150600101615671565b508097505050505050602082019150602088019750600181019050615623565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561574657605f19888603018352835180516040875261571460408801826149ad565b905060208201519150868103602088015261572f81836149ad565b9650505060209384019392909201916001016156ee565b505050506020830151848203602086015261522e8282615605565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561574657605f1988860301835283518051604087526157b360408801826149ad565b90506020820151915086810360208801526157ce81836149ad565b96505050602093840193929092019160010161578d565b6000815160e084526157fa60e0850182615199565b90506020830151848203602086015261581382826152ae565b9150506040830151848203604086015261582d82826153d9565b915050606083015184820360608601526158478282615506565b915050608083015184820360808601526158618282615594565b91505060a083015184820360a086015261587b82826156c2565b91505060c083015184820360c086015261522e8282615761565b60608152601360608201527229b4b3b730b62832b73234b733a0b1ba34b7b760691b608082015282602082015260a06040820152600061510760a08301846157e5565b6040815260006158eb60408301856149ad565b828103602084015261522e81856157e5565b60006020828403121561590f57600080fd5b81516001600160401b0381111561592557600080fd5b8201601f8101841361593657600080fd5b80516001600160401b0381111561594f5761594f614cc7565b604051601f8201601f19908116603f011681016001600160401b038111828210171561597d5761597d614cc7565b60405281815282820160200186101561599557600080fd5b61522e82602083016020860161498956fe5369676e616c576974686472617746726f6d506f736974696f6e496d70616374506f6f6ca2646970667358221220615b657aca30a2816eeb58336162b607633a4a615004e2203a5f52e71e996e6564736f6c634300081d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016a5760003560e01c8063208dd1ff1461016f5780632a083ca3146101845780632ab148dd146101a1578063314907c1146101b457806331847c96146101c7578063392bf7f6146101da5780634a4a7b041461020e5780635588ec5a14610235578063569936a414610248578063660d0d671461025b5780636d00753e14610282578063781cc3d31461029557806378b79025146102a85780637ed67107146102bb578063881be502146102ce578063990200cb146102e15780639ff78c30146102f4578063a6a58fab1461031b578063ac9650d81461032e578063ad4e4ab21461034e578063b5256f3814610361578063b971779414610374578063cd63bfa514610387578063cdb07a4f1461039a578063d0b91b01146103ad578063d597d570146103c0578063db477adc146103d3578063e38335e5146103e6578063f3388e75146103f9578063feca03a514610420575b600080fd5b61018261017d36600461453d565b610433565b005b61018e6206978081565b6040519081526020015b60405180910390f35b6101826101af3660046145af565b6105e3565b6101826101c2366004614613565b6106c7565b6101826101d5366004614646565b61094a565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b6040516101989190614688565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b61018261024336600461469c565b610d84565b610182610256366004614732565b610e29565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b610182610290366004614791565b611152565b6101826102a33660046147db565b6116b8565b6101826102b63660046147f4565b611740565b6101826102c9366004614820565b611a28565b6101826102dc366004614613565b612029565b6101826102ef36600461487e565b612259565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b6101826103293660046148b7565b6124a1565b61034161033c366004614948565b612783565b6040516101989190614a35565b61018261035c366004614a60565b612896565b61018261036f366004614aa4565b612aef565b61018261038236600461487e565b612d5e565b610182610395366004614613565b612f9f565b6101826103a8366004614613565b6131cc565b61018e6103bb366004614af9565b613445565b6101826103ce366004614a60565b6134f0565b6101826103e13660046148b7565b613749565b6101826103f4366004614af9565b613a4d565b6102017f000000000000000000000000000000000000000000000000000000000000000081565b61018e61042e3660046145af565b613af5565b6104b060405160200161046b9060208082526011908201527054494d454c4f434b5f4d554c544953494760781b604082015260600190565b604051602081830303815290604052805190602001206040518060400160405280601181526020017054494d454c4f434b5f4d554c544953494760781b815250613b99565b60405163208dd1ff60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063208dd1ff906104fe9085908590600401614bab565b600060405180830381600087803b15801561051857600080fd5b505af115801561052c573d6000803e3d6000fd5b50505050610538614430565b8051610545906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516105729160009086613cb2565b6080810151610582906001613c4d565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516105b29160009085613d0f565b6105de6040518060400160405280600a8152602001695265766f6b65526f6c6560b01b81525082613d62565b505050565b6106376040516020016105f590614bc4565b604051602081830303815290604052805190602001206040518060400160405280600e81526020016d2a24a6a2a627a1a5afa0a226a4a760911b815250613b99565b60405163134008d360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063134008d39061068e9088906000908990899089908990600401614c15565b600060405180830381600087803b1580156106a857600080fd5b505af11580156106bc573d6000803e3d6000fd5b505050505050505050565b6106d96040516020016105f590614bc4565b6001600160a01b03831661070b578260405163cb9339d560e01b81526004016107029190614688565b60405180910390fd5b600060405160200161073d906020808252600c908201526b2322a2afa922a1a2a4ab22a960a11b604082015260600190565b6040516020818303038152906040528051906020012084604051602401610765929190614c52565b60405160208183030381529060405263ca446dd960e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015610854573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108789190614c69565b6040518763ffffffff1660e01b815260040161089996959493929190614c82565b600060405180830381600087803b1580156108b357600080fd5b505af11580156108c7573d6000803e3d6000fd5b505050506108d3614430565b80516108e0906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161090d9160009088613cb2565b6109436040518060400160405280601481526020017329b4b3b730b629b2ba2332b2a932b1b2b4bb32b960611b81525082613d62565b5050505050565b61095c6040516020016105f590614bc4565b8361097c57846040516318b900b360e21b81526004016107029190614688565b6040805160028082526060820183526000926020830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106109d1576109d1614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110610a2557610a25614cdd565b6001600160a01b03929092166020928302919091019091015260408051600280825260608201909252600091816020015b6060815260200190600190039081610a56579050509050610a7687613f1f565b86604051602401610a88929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b17905281518290600090610ac557610ac5614cdd565b6020026020010181905250610ad987613f9d565b85604051602401610aeb929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110610b2a57610b2a614cdd565b6020908102919091010152604080516002808252606082019092526000918160200160208202803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb084838589897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c109190614c69565b6040518763ffffffff1660e01b8152600401610c3196959493929190614d78565b600060405180830381600087803b158015610c4b57600080fd5b505af1158015610c5f573d6000803e3d6000fd5b50505050610c6b614430565b8051610c78906001613c4d565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610ca3916000908c613cb2565b6080810151610cb3906001613c4d565b60408051808201909152601081526f195919d951185d1854dd1c99585b525960821b60208201526080820151610cec916000908b613d0f565b6020810151610cfc906001613c4d565b610d4b60006040518060400160405280601b81526020017a656467654461746153747265616d546f6b656e446563696d616c7360281b815250898460200151613d0f909392919063ffffffff16565b6106bc604051806040016040528060178152602001765369676e616c536574456467654461746153747265616d60481b81525082613d62565b610d966040516020016105f590614bc4565b60405163d0663e6160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d0663e6190610def9089906000908a908a908a908a908a90600401614ee8565b600060405180830381600087803b158015610e0957600080fd5b505af1158015610e1d573d6000803e3d6000fd5b50505050505050505050565b610e3b6040516020016105f590614bc4565b6001600160a01b038616610e6257604051634e6e36d560e11b815260040160405180910390fd5b6001600160a01b038516610e895760405163066f53b160e01b815260040160405180910390fd5b6001600160a01b038416610eb05760405163d551823d60e01b815260040160405180910390fd5b82600003610ed1576040516301d6f7b160e01b815260040160405180910390fd5b6000858585604051602401610ee893929190614f98565b604051602081830303815290604052632f1a9acf60e11b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a8860008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb9190614c69565b6040518763ffffffff1660e01b8152600401610ffc96959493929190614c82565b600060405180830381600087803b15801561101657600080fd5b505af115801561102a573d6000803e3d6000fd5b50505050611036614430565b8051611043906003613c4d565b6040805180820190915260068152651d185c99d95d60d21b6020820152815161106f916000908b613cb2565b6040805180820190915260058152643a37b5b2b760d91b6020820152815161109a916001908a613cb2565b6040805180820190915260088152673932b1b2b4bb32b960c11b602082015281516110c89160019089613cb2565b60208101516110d8906001613c4d565b611112600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151613d0f909392919063ffffffff16565b611148604051806040016040528060148152602001735369676e616c5769746864726177546f6b656e7360601b81525082613d62565b5050505050505050565b6111646040516020016105f590614bc4565b68327cb2734119d3b7a9601e1b8311156111b95760405160200161118790614fbc565b6040516020818303038152906040528051906020012083604051635ebb87c960e01b8152600401610702929190614cf3565b60408051600380825260808201909252600091602082016060803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061121057611210614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160018151811061126457611264614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816002815181106112b8576112b8614cdd565b6001600160a01b03929092166020928302919091019091015260408051600380825260808201909252600091816020015b60608152602001906001900390816112e957905050905061130988613fe0565b8760405160240161131b929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b1790528151829060009061135857611358614cdd565b602002602001018190525061136c88614014565b8660405160240161137e929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b1790528151829060019081106113bd576113bd614cdd565b60200260200101819052506113d188614050565b856040516024016113e3929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b17905281518290600290811061142257611422614cdd565b6020908102919091010152604080516003808252608082019092526000918160200160208202803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb084838589897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115089190614c69565b6040518763ffffffff1660e01b815260040161152996959493929190614d78565b600060405180830381600087803b15801561154357600080fd5b505af1158015611557573d6000803e3d6000fd5b50505050611563614430565b8051611570906001613c4d565b6040805180820190915260058152643a37b5b2b760d91b6020820152815161159b916000908d613cb2565b60808101516115ab906001613c4d565b60408051808201909152600681526519995959125960d21b602082015260808201516115da916000908c613d0f565b60208101516115ea906002613c4d565b6116326000604051806040016040528060148152602001733230ba30a9ba3932b0b6a6bab63a34b83634b2b960611b8152508a8460200151613d0f909392919063ffffffff16565b61168360016040518060400160405280601f81526020017f6461746153747265616d537072656164526564756374696f6e466163746f7200815250898460200151613d0f909392919063ffffffff16565b610e1d604051806040016040528060138152602001725369676e616c5365744461746153747265616d60681b81525082613d62565b6116ca6040516020016105f590614bc4565b60405163c4d252f560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c4d252f590602401600060405180830381600087803b15801561172c57600080fd5b505af1158015610943573d6000803e3d6000fd5b6117526040516020016105f590614bc4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d49190614c69565b83116117f6576040516373586edb60e11b815260048101849052602401610702565b6206978083111561181d57604051633ebd9bc360e21b815260048101849052602401610702565b60008360405160240161183291815260200190565b6040516020818303038152906040526364d6235360e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119459190614c69565b6040518763ffffffff1660e01b815260040161196696959493929190614c82565b600060405180830381600087803b15801561198057600080fd5b505af1158015611994573d6000803e3d6000fd5b505050506119a0614430565b60208101516119b0906001613c4d565b6119f160006040518060400160405280600d81526020016c74696d656c6f636b44656c617960981b815250878460200151613d0f909392919063ffffffff16565b61094360405180604001604052806015815260200174496e63726561736554696d656c6f636b44656c617960581b81525082613d62565b611a3a6040516020016105f590614bc4565b60408051600480825260a08201909252600091602082016080803683370190505090507f000000000000000000000000000000000000000000000000000000000000000081600081518110611a9157611a91614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611ae557611ae5614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600281518110611b3957611b39614cdd565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600381518110611b8d57611b8d614cdd565b6001600160a01b03929092166020928302919091019091015260408051600480825260a08201909252600091816020015b6060815260200190600190039081611bbe579050509050611bde89614061565b88604051602401611bf0929190614c52565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905281518290600090611c2d57611c2d614cdd565b6020026020010181905250611c4189614091565b87604051602401611c53929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110611c9257611c92614cdd565b6020026020010181905250611ca6896140cc565b86604051602401611cb8929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906002908110611cf757611cf7614cdd565b6020026020010181905250611d0b8961410f565b85604051602401611d1d929190614cf3565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906003908110611d5c57611d5c614cdd565b602090810291909101015260408051600480825260a082019092526000918160200160208202803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb084838589897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e429190614c69565b6040518763ffffffff1660e01b8152600401611e6396959493929190614d78565b600060405180830381600087803b158015611e7d57600080fd5b505af1158015611e91573d6000803e3d6000fd5b50505050611e9d614430565b8051611eaa906002613c4d565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611ed5916000908e613cb2565b6040805180820190915260098152681c1c9a58d95199595960ba1b60208201528151611f04916001908d613cb2565b6020810151611f14906003613c4d565b611f5b600060405180604001604052806013815260200172383934b1b2a332b2b226bab63a34b83634b2b960691b8152508b8460200151613d0f909392919063ffffffff16565b611fa960016040518060400160405280601a815260200179383934b1b2a332b2b22432b0b93a3132b0ba223ab930ba34b7b760311b8152508a8460200151613d0f909392919063ffffffff16565b611fe860026040518060400160405280600b81526020016a737461626c65507269636560a81b815250898460200151613d0f909392919063ffffffff16565b61201c6040518060400160405280601281526020017114da59db985b14d95d141c9a58d95199595960721b81525082613d62565b5050505050505050505050565b61203b6040516020016105f590614bc4565b6001600160a01b038316612064578260405163c1b14c9160e01b81526004016107029190614688565b6000836040516024016120779190614688565b604051602081830303815290604052630e316ab760e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612166573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218a9190614c69565b6040518763ffffffff1660e01b81526004016121ab96959493929190614c82565b600060405180830381600087803b1580156121c557600080fd5b505af11580156121d9573d6000803e3d6000fd5b505050506121e5614430565b80516121f2906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161221f9160009088613cb2565b6109436040518060400160405280601881526020017729b4b3b730b62932b6b7bb32a7b930b1b632a9b4b3b732b960411b81525082613d62565b61226b6040516020016105f590614bc4565b60008484604051602401612280929190614bab565b604051602081830303815290604052632ac9d0b760e21b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa15801561236f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123939190614c69565b6040518763ffffffff1660e01b81526004016123b496959493929190614c82565b600060405180830381600087803b1580156123ce57600080fd5b505af11580156123e2573d6000803e3d6000fd5b505050506123ee614430565b80516123fb906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516124289160009089613cb2565b6080810151612438906001613c4d565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516124689160009088613d0f565b6124996040518060400160405280600f81526020016e5369676e616c4772616e74526f6c6560881b81525082613d62565b505050505050565b6124b36040516020016105f590614bc4565b6001600160a01b0385166124da576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b0384166125015760405163d551823d60e01b815260040160405180910390fd5b8260000361252257604051630d1bbc9560e01b815260040160405180910390fd5b600085858560405160240161253993929190614f98565b604051602081830303815290604052632bae9a3560e11b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612628573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264c9190614c69565b6040518763ffffffff1660e01b815260040161266d96959493929190614c82565b600060405180830381600087803b15801561268757600080fd5b505af115801561269b573d6000803e3d6000fd5b505050506126a7614430565b80516126b4906002613c4d565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126e0916000908a613cb2565b6040805180820190915260088152673932b1b2b4bb32b960c11b6020820152815161270e9160019089613cb2565b602081015161271e906001613c4d565b612758600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151613d0f909392919063ffffffff16565b61277a6040518060600160405280602481526020016159a76024913982613d62565b50505050505050565b6060816001600160401b0381111561279d5761279d614cc7565b6040519080825280602002602001820160405280156127d057816020015b60608152602001906001900390816127bb5790505b50905060005b8281101561288f57600080308686858181106127f4576127f4614cdd565b90506020028101906128069190614fff565b604051612814929190615045565b600060405180830381855af49150503d806000811461284f576040519150601f19603f3d011682016040523d82523d6000602084013e612854565b606091505b5091509150816128675761286781614141565b8084848151811061287a5761287a614cdd565b602090810291909101015250506001016127d6565b5092915050565b6128a86040516020016105f590614bc4565b60006128b38561417a565b6040516024810191909152841515604482015260640160405160208183030381529060405263abfdcced60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129dc9190614c69565b6040518763ffffffff1660e01b81526004016129fd96959493929190614c82565b600060405180830381600087803b158015612a1757600080fd5b505af1158015612a2b573d6000803e3d6000fd5b50505050612a37614430565b8051612a44906001613c4d565b604080518082019091526008815267383937bb34b232b960c11b60208201528151612a729160009089613cb2565b6060810151612a82906001613c4d565b60408051808201909152600581526476616c756560d81b60208201526060820151612ab091600090886141b9565b6124996040518060400160405280601d81526020017f5369676e616c53657441746f6d69634f7261636c6550726f766964657200000081525082613d62565b612b016040516020016105f590614bc4565b6000612b0d868661420e565b84604051602401612b1f929190614c52565b60405160208183030381529060405263ca446dd960e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c329190614c69565b6040518763ffffffff1660e01b8152600401612c5396959493929190614c82565b600060405180830381600087803b158015612c6d57600080fd5b505af1158015612c81573d6000803e3d6000fd5b50505050612c8d614430565b8051612c9a906003613c4d565b6040805180820190915260068152656f7261636c6560d01b60208201528151612cc6916000908a613cb2565b6040805180820190915260058152643a37b5b2b760d91b60208201528151612cf19160019089613cb2565b604080518082019091526008815267383937bb34b232b960c11b60208201528151612d1f9160029088613cb2565b61277a6040518060400160405280601f81526020017f5369676e616c5365744f7261636c6550726f7669646572466f72546f6b656e0081525082613d62565b612d706040516020016105f590614bc4565b60008484604051602401612d85929190614bab565b60405160208183030381529060405263208dd1ff60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e989190614c69565b6040518763ffffffff1660e01b8152600401612eb996959493929190614c82565b600060405180830381600087803b158015612ed357600080fd5b505af1158015612ee7573d6000803e3d6000fd5b50505050612ef3614430565b8051612f00906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b60208201528151612f2d9160009089613cb2565b6080810151612f3d906001613c4d565b604080518082019091526007815266726f6c654b657960c81b60208201526080820151612f6d9160009088613d0f565b6124996040518060400160405280601081526020016f5369676e616c5265766f6b65526f6c6560801b81525082613d62565b612fb16040516020016105f590614bc4565b6001600160a01b038316612fda578260405163c1b14c9160e01b81526004016107029190614688565b600083604051602401612fed9190614688565b6040516020818303038152906040526375896b0f60e11b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131009190614c69565b6040518763ffffffff1660e01b815260040161312196959493929190614c82565b600060405180830381600087803b15801561313b57600080fd5b505af115801561314f573d6000803e3d6000fd5b5050505061315b614430565b8051613168906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516131959160009088613cb2565b6109436040518060400160405280601581526020017429b4b3b730b620b23227b930b1b632a9b4b3b732b960591b81525082613d62565b6131de6040516020016105f590614bc4565b6001600160a01b0383166132075782604051630f773b1f60e31b81526004016107029190614688565b600060405160200161323c906020808252600f908201526e484f4c44494e475f4144445245535360881b604082015260600190565b6040516020818303038152906040528051906020012084604051602401613264929190614c52565b60405160208183030381529060405263ca446dd960e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133779190614c69565b6040518763ffffffff1660e01b815260040161339896959493929190614c82565b600060405180830381600087803b1580156133b257600080fd5b505af11580156133c6573d6000803e3d6000fd5b505050506133d2614430565b80516133df906001613c4d565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161340c9160009088613cb2565b610943604051806040016040528060178152602001765369676e616c536574486f6c64696e674164647265737360481b81525082613d62565b60405163b1c5f42760e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b1c5f427906134a2908c908c908a908a908e908e908c908c90600401615055565b602060405180830381865afa1580156134bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e39190614c69565b9998505050505050505050565b6135026040516020016105f590614bc4565b600061350d856142a3565b6040516024810191909152841515604482015260640160405160208183030381529060405263abfdcced60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613612573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136369190614c69565b6040518763ffffffff1660e01b815260040161365796959493929190614c82565b600060405180830381600087803b15801561367157600080fd5b505af1158015613685573d6000803e3d6000fd5b50505050613691614430565b805161369e906001613c4d565b604080518082019091526008815267383937bb34b232b960c11b602082015281516136cc9160009089613cb2565b60608101516136dc906001613c4d565b60408051808201909152600581526476616c756560d81b6020820152606082015161370a91600090886141b9565b6124996040518060400160405280601e81526020017f5369676e616c5365744f7261636c6550726f7669646572456e61626c6564000081525082613d62565b61375b6040516020016105f590614bc4565b6001600160a01b038516613782576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b0384166137a957604051639ab5d12760e01b815260040160405180910390fd5b826000036137ca5760405163b3d3553960e01b815260040160405180910390fd5b60008585856040516024016137e193929190614f98565b60405160208183030381529060405263f128024b60e01b6001600160e01b0319166020820180516001600160e01b03838183161783525050505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a7f000000000000000000000000000000000000000000000000000000000000000060008487877f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f49190614c69565b6040518763ffffffff1660e01b815260040161391596959493929190614c82565b600060405180830381600087803b15801561392f57600080fd5b505af1158015613943573d6000803e3d6000fd5b5050505061394f614430565b805161395c906002613c4d565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151613988916000908a613cb2565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b602082015281516139bc9160019089613cb2565b60208101516139cc906001613c4d565b613a0f60006040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250878460200151613d0f909392919063ffffffff16565b61277a6040518060400160405280601c81526020017b14da59db985b1499591d58d953195b9d125b5c1858dd105b5bdd5b9d60221b81525082613d62565b613a5f6040516020016105f590614bc4565b60405163e38335e560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e38335e590613ab9908b908b908b908b908b908b908b908b90600401615055565b600060405180830381600087803b158015613ad357600080fd5b505af1158015613ae7573d6000803e3d6000fd5b505050505050505050505050565b604051638065657f60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638065657f90613b4e90899085908a908a908a908a90600401614c15565b602060405180830381865afa158015613b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8f9190614c69565b9695505050505050565b60405163ac4ab3fb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac4ab3fb90613be79033908690600401614bab565b602060405180830381865afa158015613c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2891906150c6565b613c4957338160405163a35b150b60e01b81526004016107029291906150e3565b5050565b806001600160401b03811115613c6557613c65614cc7565b604051908082528060200260200182016040528015613cab57816020015b604080518082019091526060815260006020820152815260200190600190039081613c835790505b5090915250565b8184600001518481518110613cc957613cc9614cdd565b6020026020010151600001819052508084600001518481518110613cef57613cef614cdd565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110613d2657613d26614cdd565b6020026020010151600001819052508084600001518481518110613d4c57613d4c614cdd565b6020026020010151602001818152505050505050565b613d6a614430565b600083604051602001613d7d919061510f565b604051602081830303815290604052805190602001209050613dad60018360800151613c4d90919063ffffffff16565b604080518082019091526009815268616374696f6e4b657960b81b60208201526080830151613ddf9160009084613d0f565b60c0820151613def9060016142e3565b60408051808201909152600b81526a1858dd1a5bdb931858995b60aa1b602082015260c0830151613e239160009087614345565b604051630937807960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906324de01e490613e719084908690600401615895565b600060405180830381600087803b158015613e8b57600080fd5b505af1158015613e9f573d6000803e3d6000fd5b505060405163483624fb60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063906c49f69150613ef190879087906004016158d8565b600060405180830381600087803b158015613f0b57600080fd5b505af1158015611148573d6000803e3d6000fd5b6000604051602001613f5890602080825260139082015272115111d157d110551057d4d51491505357d251606a1b604082015260600190565b6040516020818303038152906040528051906020012082604051602001613f80929190614c52565b604051602081830303815290604052805190602001209050919050565b6000604051602001613f58906020808252601f908201527f454447455f444154415f53545245414d5f544f4b454e5f444543494d414c5300604082015260600190565b6000604051602001613f58906020808252600e908201526d1110551057d4d51491505357d25160921b604082015260600190565b6000604051602001613f58906020808252601690820152752220aa20afa9aa2922a0a6afa6aaa62a24a82624a2a960511b604082015260600190565b6000604051602001613f5890614fbc565b6000604051602001613f58906020808252600a908201526914149250d157d191515160b21b604082015260600190565b6000604051602001613f5890602080825260159082015274282924a1a2afa322a2a22fa6aaa62a24a82624a2a960591b604082015260600190565b6000604051602001613f58906020808252601d908201527f50524943455f464545445f4845415254424541545f4455524154494f4e000000604082015260600190565b6000604051602001613f58906020808252600c908201526b535441424c455f505249434560a01b604082015260600190565b60008061414d83614397565b915091508015614171578160405162461bcd60e51b8152600401610702919061510f565b6105de83614427565b6000604051602001613f589060208082526019908201527824a9afa0aa27a6a4a1afa7a920a1a622afa82927ab24a222a960391b604082015260600190565b81846000015184815181106141d0576141d0614cdd565b60200260200101516000018190525080846000015184815181106141f6576141f6614cdd565b60209081029190910181015191151591015250505050565b600060405160200161424d9060208082526019908201527827a920a1a622afa82927ab24a222a92fa327a92faa27a5a2a760391b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800160405160208183030381529060405280519060200120905092915050565b6000604051602001613f58906020808252601a90820152791254d7d3d49050d31157d41493d59251115497d153905093115160321b604082015260600190565b806001600160401b038111156142fb576142fb614cc7565b604051908082528060200260200182016040528015613cab57816020015b604080518082019091526060808252602082015281526020019060019003908161431957505090915250565b818460000151848151811061435c5761435c614cdd565b602002602001015160000181905250808460000151848151811061438257614382614cdd565b60200260200101516020018190525050505050565b606060006044835110156143be575050604080516020810190915260008082529092909150565b60006143cb846020015190565b90506307b9e43360e51b6001600160e01b031982160161440a57600484019350838060200190518101906143ff91906158fd565b946001945092505050565b600060405180602001604052806000815250909250925050915091565b80518060208301fd5b604080516101208101909152606060e0820181815261010083019190915281908152602001614472604051806040016040528060608152602001606081525090565b8152602001614494604051806040016040528060608152602001606081525090565b81526020016144b6604051806040016040528060608152602001606081525090565b81526020016144d8604051806040016040528060608152602001606081525090565b81526020016144fa604051806040016040528060608152602001606081525090565b815260200161451c604051806040016040528060608152602001606081525090565b905290565b80356001600160a01b038116811461453857600080fd5b919050565b6000806040838503121561455057600080fd5b61455983614521565b946020939093013593505050565b60008083601f84011261457957600080fd5b5081356001600160401b0381111561459057600080fd5b6020830191508360208285010111156145a857600080fd5b9250929050565b6000806000806000608086880312156145c757600080fd5b6145d086614521565b945060208601356001600160401b038111156145eb57600080fd5b6145f788828901614567565b9699909850959660408101359660609091013595509350505050565b60008060006060848603121561462857600080fd5b61463184614521565b95602085013595506040909401359392505050565b600080600080600060a0868803121561465e57600080fd5b61466786614521565b97602087013597506040870135966060810135965060800135945092505050565b6001600160a01b0391909116815260200190565b60008060008060008060a087890312156146b557600080fd5b6146be87614521565b955060208701356001600160401b038111156146d957600080fd5b6146e589828a01614567565b909650945050604087013592506060870135915060808701356001600160401b0381111561471257600080fd5b87016060818a03121561472457600080fd5b809150509295509295509295565b60008060008060008060c0878903121561474b57600080fd5b61475487614521565b955061476260208801614521565b945061477060408801614521565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008060008060c087890312156147aa57600080fd5b6147b387614521565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b6000602082840312156147ed57600080fd5b5035919050565b60008060006060848603121561480957600080fd5b505081359360208301359350604090920135919050565b600080600080600080600060e0888a03121561483b57600080fd5b61484488614521565b965061485260208901614521565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b6000806000806080858703121561489457600080fd5b61489d85614521565b966020860135965060408601359560600135945092505050565b600080600080600060a086880312156148cf57600080fd5b6148d886614521565b94506148e660208701614521565b94979496505050506040830135926060810135926080909101359150565b60008083601f84011261491657600080fd5b5081356001600160401b0381111561492d57600080fd5b6020830191508360208260051b85010111156145a857600080fd5b6000806020838503121561495b57600080fd5b82356001600160401b0381111561497157600080fd5b61497d85828601614904565b90969095509350505050565b60005b838110156149a457818101518382015260200161498c565b50506000910152565b600081518084526149c5816020860160208601614989565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852614a138383516149ad565b60209889019890935091909101906001016149f7565b50909695505050505050565b602081526000614a4860208301846149d9565b9392505050565b8015158114614a5d57600080fd5b50565b60008060008060808587031215614a7657600080fd5b614a7f85614521565b93506020850135614a8f81614a4f565b93969395505050506040820135916060013590565b600080600080600060a08688031215614abc57600080fd5b614ac586614521565b9450614ad360208701614521565b9350614ae160408701614521565b94979396509394606081013594506080013592915050565b60008060008060008060008060a0898b031215614b1557600080fd5b88356001600160401b03811115614b2b57600080fd5b614b378b828c01614904565b90995097505060208901356001600160401b03811115614b5657600080fd5b614b628b828c01614904565b90975095505060408901356001600160401b03811115614b8157600080fd5b614b8d8b828c01614904565b999c989b509699959896976060870135966080013595509350505050565b6001600160a01b03929092168252602082015260400190565b6020808252600e908201526d2a24a6a2a627a1a5afa0a226a4a760911b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a060408201526000614c3d60a083018688614bec565b60608301949094525060800152949350505050565b9182526001600160a01b0316602082015260400190565b600060208284031215614c7b57600080fd5b5051919050565b60018060a01b038716815285602082015260c060408201526000614ca960c08301876149ad565b606083019590955250608081019290925260a0909101529392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b918252602082015260400190565b600081518084526020840193506020830160005b82811015614d3c5781516001600160a01b0316865260209586019590910190600101614d15565b5093949350505050565b600081518084526020840193506020830160005b82811015614d3c578151865260209586019590910190600101614d5a565b60c081526000614d8b60c0830189614d01565b8281036020840152614d9d8189614d46565b90508281036040840152614db181886149d9565b60608401969096525050608081019290925260a0909101529392505050565b6000808335601e19843603018112614de757600080fd5b83016020810192503590506001600160401b03811115614e0657600080fd5b8060051b36038213156145a857600080fd5b81835260208301925060008160005b84811015614d3c576001600160a01b03614e4083614521565b1686526020958601959190910190600101614e27565b60008383855260208501945060208460051b8201018360005b86811015614a2957838303601f19018852600080833536899003601e19018112614e97578283fd5b88016020810192503590506001600160401b03811115614eb657600080fd5b803603821315614ec557600080fd5b614ed0858284614bec565b60209a8b019a90955093909301925050600101614e6f565b60018060a01b038816815286602082015260c060408201526000614f1060c083018789614bec565b85606084015284608084015282810360a0840152614f2e8485614dd0565b60608352614f40606084018284614e18565b915050614f506020860186614dd0565b8383036020850152614f63838284614e18565b92505050614f746040860186614dd0565b8383036040850152614f87838284614e56565b9d9c50505050505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526023908201527f444154415f53545245414d5f5350524541445f524544554354494f4e5f4641436040820152622a27a960e91b606082015260800190565b6000808335601e1984360301811261501657600080fd5b8301803591506001600160401b0382111561503057600080fd5b6020019150368190038213156145a857600080fd5b8183823760009101908152919050565b60a08152600061506960a083018a8c614e18565b82810360208401528781526001600160fb1b0388111561508857600080fd5b8760051b808a602084013701828103602090810160408501526150ae9082018789614e56565b60608401959095525050608001529695505050505050565b6000602082840312156150d857600080fd5b8151614a4881614a4f565b6001600160a01b0383168152604060208201819052600090615107908301846149ad565b949350505050565b602081526000614a4860208301846149ad565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261516660408601826149ad565b90506020820151915084810360208601526151818183614d01565b60209a8b019a90955093909301925050600101615140565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561521357605f1988860301835283518051604087526151eb60408801826149ad565b6020928301516001600160a01b031697830197909752509384019392909201916001016151c5565b505050506020830151848203602086015261522e8282615122565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261527b60408601826149ad565b90506020820151915084810360208601526152968183614d46565b60209a8b019a90955093909301925050600101615255565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561531f57605f19888603018352835180516040875261530060408801826149ad565b60209283015197830197909752509384019392909201916001016152da565b505050506020830151848203602086015261522e8282615237565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261537e60408601826149ad565b6020928301518682038785015280518083529084019360009350909101905b808310156153c0578351825260208201915060208401935060018301925061539d565b5060209a8b019a90955093909301925050600101615358565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561544a57605f19888603018352835180516040875261542b60408801826149ad565b6020928301519783019790975250938401939290920191600101615405565b505050506020830151848203602086015261522e828261533a565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f1985840301885281518051604085526154a960408601826149ad565b6020928301518682038785015280518083529084019360009350909101905b808310156154ed578351151582526020820191506020840193506001830192506154c8565b5060209a8b019a90955093909301925050600101615483565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561557957605f19888603018352835180516040875261555860408801826149ad565b60209283015115159783019790975250938401939290920191600101615532565b505050506020830151848203602086015261522e8282615465565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561544a57605f1988860301835283518051604087526155e660408801826149ad565b60209283015197830197909752509384019392909201916001016155c0565b600082825180855260208501945060208160051b8301016020850160005b83811015614a2957601f19858403018852815180516040855261564960408601826149ad565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b828110156156a257601f1985830301845261568d8287516149ad565b60209687019694909401939150600101615671565b508097505050505050602082019150602088019750600181019050615623565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561574657605f19888603018352835180516040875261571460408801826149ad565b905060208201519150868103602088015261572f81836149ad565b9650505060209384019392909201916001016156ee565b505050506020830151848203602086015261522e8282615605565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561574657605f1988860301835283518051604087526157b360408801826149ad565b90506020820151915086810360208801526157ce81836149ad565b96505050602093840193929092019160010161578d565b6000815160e084526157fa60e0850182615199565b90506020830151848203602086015261581382826152ae565b9150506040830151848203604086015261582d82826153d9565b915050606083015184820360608601526158478282615506565b915050608083015184820360808601526158618282615594565b91505060a083015184820360a086015261587b82826156c2565b91505060c083015184820360c086015261522e8282615761565b60608152601360608201527229b4b3b730b62832b73234b733a0b1ba34b7b760691b608082015282602082015260a06040820152600061510760a08301846157e5565b6040815260006158eb60408301856149ad565b828103602084015261522e81856157e5565b60006020828403121561590f57600080fd5b81516001600160401b0381111561592557600080fd5b8201601f8101841361593657600080fd5b80516001600160401b0381111561594f5761594f614cc7565b604051601f8201601f19908116603f011681016001600160401b038111828210171561597d5761597d614cc7565b60405281815282820160200186101561599557600080fd5b61522e82602083016020860161498956fe5369676e616c576974686472617746726f6d506f736974696f6e496d70616374506f6f6ca2646970667358221220615b657aca30a2816eeb58336162b607633a4a615004e2203a5f52e71e996e6564736f6c634300081d0033", + "numDeployments": 5, + "solcInputHash": "02b1f859efc9c56ded8960da79621723", + "metadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"_eventEmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dataStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_oracleStore\",\"type\":\"address\"},{\"internalType\":\"contract RoleStore\",\"name\":\"_roleStore\",\"type\":\"address\"},{\"internalType\":\"contract ConfigTimelockController\",\"name\":\"_timelockController\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"baseKey\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"ConfigValueExceedsAllowedRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"EmptyDataStreamFeedId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyFundingAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyMarket\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPositionImpactWithdrawalAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReduceLentAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyWithdrawalAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidContributorToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"InvalidFeeReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"InvalidHoldingAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidOracleSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokensLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountsLength\",\"type\":\"uint256\"}],\"name\":\"InvalidSetMaxTotalContributorTokenAmountInput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timelockDelay\",\"type\":\"uint256\"}],\"name\":\"InvalidTimelockDelay\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timelockDelay\",\"type\":\"uint256\"}],\"name\":\"MaxTimelockDelayExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"}],\"name\":\"MinContributorPaymentIntervalBelowAllowedRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"role\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MAX_TIMELOCK_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"cancelAction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dataStore\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventEmitter\",\"outputs\":[{\"internalType\":\"contract EventEmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"providers\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"internalType\":\"struct OracleUtils.SetPricesParams\",\"name\":\"oracleParams\",\"type\":\"tuple\"}],\"name\":\"executeWithOraclePrice\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"getHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"payloads\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"getHashBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timelockDelay\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"increaseTimelockDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleStore\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"roleKey\",\"type\":\"bytes32\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"roleStore\",\"outputs\":[{\"internalType\":\"contract RoleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalAddOracleSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"roleKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalGrantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fundingAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"reductionAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalReduceLentAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalRemoveOracleSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"roleKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalRevokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetAtomicOracleProvider\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dataStreamMultiplier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataStreamSpreadReductionFactor\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetDataStream\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"edgeDataStreamId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"edgeDataStreamTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetEdgeDataStream\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetFeeReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetHoldingAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetMaxTotalContributorTokenAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetMinContributorPaymentInterval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetOracleProviderEnabled\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetOracleProviderForToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"priceFeedMultiplier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"priceFeedHeartbeatDuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"stablePrice\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalSetPriceFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalWithdrawFromPositionImpactPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"signalWithdrawTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timelockController\",\"outputs\":[{\"internalType\":\"contract ConfigTimelockController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"multicall(bytes[])\":{\"details\":\"Receives and executes a batch of function calls on this contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/config/TimelockConfig.sol\":\"TimelockConfig\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorInterface {\\n function latestAnswer() external view returns (int256);\\n\\n function latestTimestamp() external view returns (uint256);\\n\\n function latestRound() external view returns (uint256);\\n\\n function getAnswer(uint256 roundId) external view returns (int256);\\n\\n function getTimestamp(uint256 roundId) external view returns (uint256);\\n\\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\\n\\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\\n}\\n\",\"keccak256\":\"0xb496651006b9a2a07920ffe116928b11e2a6458e21361cecca51409522488ca7\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {AggregatorInterface} from \\\"./AggregatorInterface.sol\\\";\\nimport {AggregatorV3Interface} from \\\"./AggregatorV3Interface.sol\\\";\\n\\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\\n\",\"keccak256\":\"0xee12d80dbdbb3cc0ec10372b9323e42fae9a6de45da5a4e9f7a75223a0b5268b\",\"license\":\"MIT\"},\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n function getRoundData(\\n uint80 _roundId\\n ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n\\n function latestRoundData()\\n external\\n view\\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\\n}\\n\",\"keccak256\":\"0xfe4e8bb4861bb3860ba890ab91a3b818ec66e5a8f544fb608cfcb73f433472cd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```solidity\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```solidity\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\\n * to enforce additional security measures for this role.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role);\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\\n * Overriding this function changes the behavior of the {onlyRole} modifier.\\n *\\n * Format of the revert message is described in {_checkRole}.\\n *\\n * _Available since v4.6._\\n */\\n function _checkRole(bytes32 role) internal view virtual {\\n _checkRole(role, _msgSender());\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view virtual {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(account),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * May emit a {RoleGranted} event.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n *\\n * NOTE: This function is deprecated in favor of {_grantRole}.\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n bytes32 previousAdminRole = getRoleAdmin(role);\\n _roles[role].adminRole = adminRole;\\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleGranted} event.\\n */\\n function _grantRole(bytes32 role, address account) internal virtual {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * Internal function without access restriction.\\n *\\n * May emit a {RoleRevoked} event.\\n */\\n function _revokeRole(bytes32 role, address account) internal virtual {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0dd6e52cb394d7f5abe5dca2d4908a6be40417914720932de757de34a99ab87f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/governance/TimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../access/AccessControl.sol\\\";\\nimport \\\"../token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"../token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Contract module which acts as a timelocked controller. When set as the\\n * owner of an `Ownable` smart contract, it enforces a timelock on all\\n * `onlyOwner` maintenance operations. This gives time for users of the\\n * controlled contract to exit before a potentially dangerous maintenance\\n * operation is applied.\\n *\\n * By default, this contract is self administered, meaning administration tasks\\n * have to go through the timelock process. The proposer (resp executor) role\\n * is in charge of proposing (resp executing) operations. A common use case is\\n * to position this {TimelockController} as the owner of a smart contract, with\\n * a multisig or a DAO as the sole proposer.\\n *\\n * _Available since v3.3._\\n */\\ncontract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {\\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\\\"TIMELOCK_ADMIN_ROLE\\\");\\n bytes32 public constant PROPOSER_ROLE = keccak256(\\\"PROPOSER_ROLE\\\");\\n bytes32 public constant EXECUTOR_ROLE = keccak256(\\\"EXECUTOR_ROLE\\\");\\n bytes32 public constant CANCELLER_ROLE = keccak256(\\\"CANCELLER_ROLE\\\");\\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\\n\\n mapping(bytes32 => uint256) private _timestamps;\\n uint256 private _minDelay;\\n\\n /**\\n * @dev Emitted when a call is scheduled as part of operation `id`.\\n */\\n event CallScheduled(\\n bytes32 indexed id,\\n uint256 indexed index,\\n address target,\\n uint256 value,\\n bytes data,\\n bytes32 predecessor,\\n uint256 delay\\n );\\n\\n /**\\n * @dev Emitted when a call is performed as part of operation `id`.\\n */\\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\\n\\n /**\\n * @dev Emitted when new proposal is scheduled with non-zero salt.\\n */\\n event CallSalt(bytes32 indexed id, bytes32 salt);\\n\\n /**\\n * @dev Emitted when operation `id` is cancelled.\\n */\\n event Cancelled(bytes32 indexed id);\\n\\n /**\\n * @dev Emitted when the minimum delay for future operations is modified.\\n */\\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\\n\\n /**\\n * @dev Initializes the contract with the following parameters:\\n *\\n * - `minDelay`: initial minimum delay for operations\\n * - `proposers`: accounts to be granted proposer and canceller roles\\n * - `executors`: accounts to be granted executor role\\n * - `admin`: optional account to be granted admin role; disable with zero address\\n *\\n * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment\\n * without being subject to delay, but this role should be subsequently renounced in favor of\\n * administration through timelocked proposals. Previous versions of this contract would assign\\n * this admin to the deployer automatically and should be renounced as well.\\n */\\n constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {\\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);\\n\\n // self administration\\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\\n\\n // optional admin\\n if (admin != address(0)) {\\n _setupRole(TIMELOCK_ADMIN_ROLE, admin);\\n }\\n\\n // register proposers and cancellers\\n for (uint256 i = 0; i < proposers.length; ++i) {\\n _setupRole(PROPOSER_ROLE, proposers[i]);\\n _setupRole(CANCELLER_ROLE, proposers[i]);\\n }\\n\\n // register executors\\n for (uint256 i = 0; i < executors.length; ++i) {\\n _setupRole(EXECUTOR_ROLE, executors[i]);\\n }\\n\\n _minDelay = minDelay;\\n emit MinDelayChange(0, minDelay);\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only by a certain role. In\\n * addition to checking the sender's role, `address(0)` 's role is also\\n * considered. Granting a role to `address(0)` is equivalent to enabling\\n * this role for everyone.\\n */\\n modifier onlyRoleOrOpenRole(bytes32 role) {\\n if (!hasRole(role, address(0))) {\\n _checkRole(role, _msgSender());\\n }\\n _;\\n }\\n\\n /**\\n * @dev Contract might receive/hold ETH as part of the maintenance process.\\n */\\n receive() external payable {}\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns whether an id correspond to a registered operation. This\\n * includes both Pending, Ready and Done operations.\\n */\\n function isOperation(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > 0;\\n }\\n\\n /**\\n * @dev Returns whether an operation is pending or not. Note that a \\\"pending\\\" operation may also be \\\"ready\\\".\\n */\\n function isOperationPending(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) > _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns whether an operation is ready for execution. Note that a \\\"ready\\\" operation is also \\\"pending\\\".\\n */\\n function isOperationReady(bytes32 id) public view virtual returns (bool) {\\n uint256 timestamp = getTimestamp(id);\\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\\n }\\n\\n /**\\n * @dev Returns whether an operation is done or not.\\n */\\n function isOperationDone(bytes32 id) public view virtual returns (bool) {\\n return getTimestamp(id) == _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns the timestamp at which an operation becomes ready (0 for\\n * unset operations, 1 for done operations).\\n */\\n function getTimestamp(bytes32 id) public view virtual returns (uint256) {\\n return _timestamps[id];\\n }\\n\\n /**\\n * @dev Returns the minimum delay for an operation to become valid.\\n *\\n * This value can be changed by executing an operation that calls `updateDelay`.\\n */\\n function getMinDelay() public view virtual returns (uint256) {\\n return _minDelay;\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a single\\n * transaction.\\n */\\n function hashOperation(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(target, value, data, predecessor, salt));\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a batch of\\n * transactions.\\n */\\n function hashOperationBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32) {\\n return keccak256(abi.encode(targets, values, payloads, predecessor, salt));\\n }\\n\\n /**\\n * @dev Schedule an operation containing a single transaction.\\n *\\n * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function schedule(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\\n _schedule(id, delay);\\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation containing a batch of transactions.\\n *\\n * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function scheduleBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n _schedule(id, delay);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);\\n }\\n if (salt != bytes32(0)) {\\n emit CallSalt(id, salt);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation that is to become valid after a given delay.\\n */\\n function _schedule(bytes32 id, uint256 delay) private {\\n require(!isOperation(id), \\\"TimelockController: operation already scheduled\\\");\\n require(delay >= getMinDelay(), \\\"TimelockController: insufficient delay\\\");\\n _timestamps[id] = block.timestamp + delay;\\n }\\n\\n /**\\n * @dev Cancel an operation.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'canceller' role.\\n */\\n function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {\\n require(isOperationPending(id), \\\"TimelockController: operation cannot be cancelled\\\");\\n delete _timestamps[id];\\n\\n emit Cancelled(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a single transaction.\\n *\\n * Emits a {CallExecuted} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function execute(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n bytes32 id = hashOperation(target, value, payload, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n _execute(target, value, payload);\\n emit CallExecuted(id, 0, target, value, payload);\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a batch of transactions.\\n *\\n * Emits one {CallExecuted} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\\n // thus any modifications to the operation during reentrancy should be caught.\\n // slither-disable-next-line reentrancy-eth\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == payloads.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\\n\\n _beforeCall(id, predecessor);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n address target = targets[i];\\n uint256 value = values[i];\\n bytes calldata payload = payloads[i];\\n _execute(target, value, payload);\\n emit CallExecuted(id, i, target, value, payload);\\n }\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an operation's call.\\n */\\n function _execute(address target, uint256 value, bytes calldata data) internal virtual {\\n (bool success, ) = target.call{value: value}(data);\\n require(success, \\\"TimelockController: underlying transaction reverted\\\");\\n }\\n\\n /**\\n * @dev Checks before execution of an operation's calls.\\n */\\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \\\"TimelockController: missing dependency\\\");\\n }\\n\\n /**\\n * @dev Checks after execution of an operation's calls.\\n */\\n function _afterCall(bytes32 id) private {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n _timestamps[id] = _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Changes the minimum timelock duration for future operations.\\n *\\n * Emits a {MinDelayChange} event.\\n *\\n * Requirements:\\n *\\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\\n */\\n function updateDelay(uint256 newDelay) external virtual {\\n require(msg.sender == address(this), \\\"TimelockController: caller must be timelock\\\");\\n emit MinDelayChange(_minDelay, newDelay);\\n _minDelay = newDelay;\\n }\\n\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155Received}.\\n */\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n /**\\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\\n */\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xda2a70247fda81633d9392f567a401c4772837de6b0543c1c561ca632a2fe7f4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x9f4357008a8f7d8c8bf5d48902e789637538d8c016be5766610901b4bba81514\",\"license\":\"MIT\"},\"contracts/bank/Bank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../token/TokenUtils.sol\\\";\\nimport \\\"../role/RoleModule.sol\\\";\\n\\n// @title Bank\\n// @dev Contract to handle storing and transferring of tokens\\ncontract Bank is RoleModule {\\n using SafeERC20 for IERC20;\\n\\n DataStore public immutable dataStore;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n }\\n\\n receive() external payable {\\n address wnt = TokenUtils.wnt(dataStore);\\n if (msg.sender != wnt) {\\n revert Errors.InvalidNativeTokenSender(msg.sender);\\n }\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n _transferOut(token, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n // handles native token transfers as well\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOut(\\n address token,\\n address receiver,\\n uint256 amount,\\n bool shouldUnwrapNativeToken\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n\\n if (token == wnt && shouldUnwrapNativeToken) {\\n _transferOutNativeToken(token, receiver, amount);\\n } else {\\n _transferOut(token, receiver, amount);\\n }\\n }\\n\\n // @dev transfer native tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\\n // before transferring\\n function transferOutNativeToken(\\n address receiver,\\n uint256 amount\\n ) external onlyController {\\n address wnt = TokenUtils.wnt(dataStore);\\n _transferOutNativeToken(wnt, receiver, amount);\\n }\\n\\n // @dev transfer tokens from this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOut(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.transfer(dataStore, token, receiver, amount);\\n\\n _afterTransferOut(token);\\n }\\n\\n // @dev unwrap wrapped native tokens and transfer the native tokens from\\n // this contract to a receiver\\n //\\n // @param token the token to transfer\\n // @param amount the amount to transfer\\n // @param receiver the address to transfer to\\n function _transferOutNativeToken(\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (receiver == address(this)) {\\n revert Errors.SelfTransferNotSupported(receiver);\\n }\\n\\n TokenUtils.withdrawAndSendNativeToken(\\n dataStore,\\n token,\\n receiver,\\n amount\\n );\\n\\n _afterTransferOut(token);\\n }\\n\\n function _afterTransferOut(address /* token */) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd81882fe131c1458e5da01b50190ed60daa1f20acc8a522fc23a51eee4c26f4d\",\"license\":\"BUSL-1.1\"},\"contracts/bank/StrictBank.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./Bank.sol\\\";\\n\\n// @title StrictBank\\n// @dev a stricter version of Bank\\n//\\n// the Bank contract does not have functions to validate the amount of tokens\\n// transferred in\\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\\n// and that tokens were transferred into it if there was no revert\\n//\\n// the StrictBank contract keeps track of its internal token balance\\n// and uses recordTransferIn to compare its change in balance and return\\n// the amount of tokens received\\ncontract StrictBank is Bank {\\n using SafeERC20 for IERC20;\\n\\n // used to record token balances to evaluate amounts transferred in\\n mapping (address => uint256) public tokenBalances;\\n\\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function recordTransferIn(address token) external onlyController returns (uint256) {\\n return _recordTransferIn(token);\\n }\\n\\n // @dev this can be used to update the tokenBalances in case of token burns\\n // or similar balance changes\\n // the prevBalance is not validated to be more than the nextBalance as this\\n // could allow someone to block this call by transferring into the contract\\n // @param token the token to record the burn for\\n // @return the new balance\\n function syncTokenBalance(address token) external onlyController returns (uint256) {\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n return nextBalance;\\n }\\n\\n // @dev records a token transfer into the contract\\n // @param token the token to record the transfer for\\n // @return the amount of tokens transferred in\\n function _recordTransferIn(address token) internal returns (uint256) {\\n uint256 prevBalance = tokenBalances[token];\\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\\n tokenBalances[token] = nextBalance;\\n\\n return nextBalance - prevBalance;\\n }\\n\\n // @dev update the internal balance after tokens have been transferred out\\n // this is called from the Bank contract\\n // @param token the token that was transferred out\\n function _afterTransferOut(address token) internal override {\\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x4ebe920c2925c1611b60de831636c5761a9fc90ae175ec8a7351fe2d6db13edd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbGasInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbGasInfo\\ninterface ArbGasInfo {\\n function getCurrentTxL1GasFees() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x48c4ffaab45cc49cf4d4014eaf92867b65f7cf5c20deca5199e746d72c197816\",\"license\":\"BUSL-1.1\"},\"contracts/chain/ArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title ArbSys\\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\\n// value, the ArbSys interface is used to retrieve the L2 value\\ninterface ArbSys {\\n function arbBlockNumber() external view returns (uint256);\\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x97a2fcc4828af974d9e763db893b1188fec4d964ec3896611284678631dc5ffd\",\"license\":\"BUSL-1.1\"},\"contracts/chain/Chain.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ArbSys.sol\\\";\\nimport \\\"./ArbGasInfo.sol\\\";\\n\\n// @title Chain\\n// @dev Wrap the calls to retrieve chain variables to handle differences\\n// between chain implementations\\nlibrary Chain {\\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\\n // and contracts depending on it would need to be deployed\\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\\n\\n ArbSys public constant arbSys = ArbSys(address(100));\\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\\n\\n // @dev return the current block's timestamp\\n // @return the current block's timestamp\\n function currentTimestamp() internal view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n // @dev return the current block's number\\n // @return the current block's number\\n function currentBlockNumber() internal view returns (uint256) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockNumber();\\n }\\n\\n return block.number;\\n }\\n\\n // @dev return the current block's hash\\n // @return the current block's hash\\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\\n if (shouldUseArbPrecompiles()) {\\n return arbSys.arbBlockHash(blockNumber);\\n }\\n\\n return blockhash(blockNumber);\\n }\\n\\n function shouldUseArbPrecompiles() internal view returns (bool) {\\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\\n }\\n\\n function getCurrentTxL1GasFees() internal view returns (uint256) {\\n if (!shouldUseArbPrecompiles()) {\\n return 0;\\n }\\n return arbGasInfo.getCurrentTxL1GasFees();\\n }\\n}\\n\",\"keccak256\":\"0x6aaf3c482b05293c1d7582182e5453a25d4e87aa7d51388865d11984daba94cd\",\"license\":\"BUSL-1.1\"},\"contracts/config/ConfigTimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {EventUtils} from \\\"../event/EventUtils.sol\\\";\\nimport {Multicall3} from \\\"../mock/Multicall3.sol\\\";\\nimport {OracleStore} from \\\"../oracle/OracleStore.sol\\\";\\nimport {RoleStore} from \\\"../role/RoleStore.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {TimelockController} from \\\"@openzeppelin/contracts/governance/TimelockController.sol\\\";\\nimport {OracleModule} from \\\"../oracle/OracleModule.sol\\\";\\nimport {OracleUtils} from \\\"../oracle/OracleUtils.sol\\\";\\nimport {Oracle} from \\\"../oracle/Oracle.sol\\\";\\nimport {PositionImpactPoolUtils} from \\\"../market/PositionImpactPoolUtils.sol\\\";\\nimport {Chain} from \\\"../chain/Chain.sol\\\";\\nimport {AccountUtils} from \\\"../utils/AccountUtils.sol\\\";\\n\\ncontract ConfigTimelockController is TimelockController, OracleModule {\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n\\n constructor(\\n uint256 minDelay,\\n address[] memory proposers,\\n address[] memory executors,\\n Oracle oracle,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter\\n ) TimelockController(minDelay, proposers, executors, msg.sender) OracleModule(oracle) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n }\\n\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n // note that if on-chain prices are used for market operations, there may\\n // be some difference in pricing between the on-chain price and e.g.\\n // an off-chain data stream price\\n // it should be ensured that the changes to the market token price that\\n // result from this execution are not too large that it would lead to\\n // significant arbitrage opportunities\\n function executeWithOraclePrices(\\n address target,\\n uint256 value,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt,\\n OracleUtils.SetPricesParams calldata oracleParams\\n ) external onlyRoleOrOpenRole(EXECUTOR_ROLE) withOraclePricesForAtomicAction(oracleParams) {\\n execute(target, value, payload, predecessor, salt);\\n }\\n\\n function withdrawFromPositionImpactPool(\\n address market,\\n address receiver,\\n uint256 amount\\n ) external onlySelf {\\n PositionImpactPoolUtils.withdrawFromPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentImpactAmount(\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external onlySelf {\\n PositionImpactPoolUtils.reduceLentAmount(\\n dataStore,\\n eventEmitter,\\n oracle,\\n market,\\n fundingAccount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xfd4e8cf25c70dc3e8b14f59067edbacd134a7e3a1294250f7b0392049b51ddbf\",\"license\":\"BUSL-1.1\"},\"contracts/config/TimelockConfig.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {EventUtils} from \\\"../event/EventUtils.sol\\\";\\nimport {RoleModule} from \\\"../role/RoleModule.sol\\\";\\nimport {RoleStore} from \\\"../role/RoleStore.sol\\\";\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {BasicMulticall} from \\\"../utils/BasicMulticall.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {ConfigTimelockController} from \\\"./ConfigTimelockController.sol\\\";\\nimport {OracleModule} from \\\"../oracle/OracleModule.sol\\\";\\nimport {OracleUtils} from \\\"../oracle/OracleUtils.sol\\\";\\nimport {MarketUtils} from \\\"../market/MarketUtils.sol\\\";\\n\\ncontract TimelockConfig is RoleModule, BasicMulticall {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n uint256 public constant MAX_TIMELOCK_DELAY = 5 days;\\n\\n EventEmitter public immutable eventEmitter;\\n ConfigTimelockController public immutable timelockController;\\n\\n address public immutable dataStore;\\n address public immutable oracleStore;\\n\\n constructor(\\n EventEmitter _eventEmitter,\\n address _dataStore,\\n address _oracleStore,\\n RoleStore _roleStore,\\n ConfigTimelockController _timelockController\\n ) RoleModule(_roleStore) {\\n eventEmitter = _eventEmitter;\\n dataStore = _dataStore;\\n oracleStore = _oracleStore;\\n timelockController = _timelockController;\\n }\\n\\n // @dev signal granting of a role\\n // @param account the account to grant the role\\n // @param roleKey the role to grant\\n function signalGrantRole(address account, bytes32 roleKey, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"grantRole(address,bytes32)\\\", account, roleKey);\\n _schedule(address(roleStore), payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"roleKey\\\", roleKey);\\n _signalPendingAction(\\n \\\"SignalGrantRole\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal revoking of a role\\n // @param account the account to revoke the role for\\n // @param roleKey the role to revoke\\n function signalRevokeRole(address account, bytes32 roleKey, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"revokeRole(address,bytes32)\\\",\\n account, roleKey);\\n _schedule(address(roleStore), payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"roleKey\\\", roleKey);\\n _signalPendingAction(\\n \\\"SignalRevokeRole\\\",\\n eventData\\n );\\n }\\n\\n // @dev immediately revoke the role of an account\\n // @param account the account to revoke the role for\\n // @param roleKey the role to revoke\\n function revokeRole(address account, bytes32 roleKey) external onlyTimelockMultisig {\\n roleStore.revokeRole(account, roleKey);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"roleKey\\\", roleKey);\\n _signalPendingAction(\\n \\\"RevokeRole\\\",\\n eventData\\n );\\n }\\n\\n function signalSetOracleProviderEnabled(address provider, bool value, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"setBool(bytes32,bool)\\\",\\n Keys.isOracleProviderEnabledKey(provider), value);\\n _schedule(dataStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"provider\\\", provider);\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"value\\\", value);\\n _signalPendingAction(\\n \\\"SignalSetOracleProviderEnabled\\\",\\n eventData\\n );\\n }\\n\\n function signalSetOracleProviderForToken(address oracle, address token, address provider, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.oracleProviderForTokenKey(oracle, token), provider);\\n _schedule(dataStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"oracle\\\", oracle);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"provider\\\", provider);\\n _signalPendingAction(\\n \\\"SignalSetOracleProviderForToken\\\",\\n eventData\\n );\\n }\\n\\n function signalSetAtomicOracleProvider(address provider, bool value, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n bytes memory payload = abi.encodeWithSignature(\\\"setBool(bytes32,bool)\\\",\\n Keys.isAtomicOracleProviderKey(provider), value);\\n _schedule(dataStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"provider\\\", provider);\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"value\\\", value);\\n _signalPendingAction(\\n \\\"SignalSetAtomicOracleProvider\\\",\\n eventData\\n );\\n }\\n\\n function signalAddOracleSigner(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidOracleSigner(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"addSigner(address)\\\", account);\\n _schedule(oracleStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalAddOracleSigner\\\",\\n eventData\\n );\\n }\\n\\n function signalRemoveOracleSigner(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidOracleSigner(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"removeSigner(address)\\\", account);\\n _schedule(oracleStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalRemoveOracleSigner\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of the fee receiver\\n // @param account the new fee receiver\\n function signalSetFeeReceiver(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidFeeReceiver(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.FEE_RECEIVER, account);\\n _schedule(dataStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalSetFeeReceiver\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of the holding address\\n // @param account of the new holding address\\n function signalSetHoldingAddress(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (account == address(0)) {\\n revert Errors.InvalidHoldingAddress(account);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.HOLDING_ADDRESS, account);\\n _schedule(dataStore, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n _signalPendingAction(\\n \\\"SignalSetHoldingAddress\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of a price feed\\n // @param token the token to set the price feed for\\n // @param priceFeed the address of the price feed\\n // @param priceFeedMultiplier the multiplier to apply to the price feed results\\n // @param stablePrice the stable price to set a range for the price feed results\\n function signalSetPriceFeed(\\n address token,\\n address priceFeed,\\n uint256 priceFeedMultiplier,\\n uint256 priceFeedHeartbeatDuration,\\n uint256 stablePrice,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n\\n bytes[] memory payloads = new bytes[](4);\\n payloads[0] = abi.encodeWithSignature(\\\"setAddress(bytes32,address)\\\",\\n Keys.priceFeedKey(token), priceFeed);\\n payloads[1] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.priceFeedMultiplierKey(token), priceFeedMultiplier);\\n payloads[2] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration);\\n payloads[3] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.stablePriceKey(token), stablePrice);\\n\\n _scheduleBatch(dataStore, payloads, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"priceFeed\\\", priceFeed);\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"priceFeedMultiplier\\\", priceFeedMultiplier);\\n eventData.uintItems.setItem(1, \\\"priceFeedHeartbeatDuration\\\", priceFeedHeartbeatDuration);\\n eventData.uintItems.setItem(2, \\\"stablePrice\\\", stablePrice);\\n _signalPendingAction(\\n \\\"SignalSetPriceFeed\\\",\\n eventData\\n );\\n }\\n\\n // @dev signal setting of a data stream feed\\n // @param token the token to set the data stream feed for\\n // @param feedId the ID of the data stream feed\\n // @param dataStreamMultiplier the multiplier to apply to the data stream feed results\\n // @param dataStreamSpreadReductionFactor the factor to apply to the data stream price spread\\n function signalSetDataStream(\\n address token,\\n bytes32 feedId,\\n uint256 dataStreamMultiplier,\\n uint256 dataStreamSpreadReductionFactor,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (dataStreamSpreadReductionFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.ConfigValueExceedsAllowedRange(Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR, dataStreamSpreadReductionFactor);\\n }\\n\\n bytes[] memory payloads = new bytes[](3);\\n payloads[0] = abi.encodeWithSignature(\\\"setBytes32(bytes32,bytes32)\\\",\\n Keys.dataStreamIdKey(token), feedId);\\n payloads[1] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.dataStreamMultiplierKey(token), dataStreamMultiplier);\\n payloads[2] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.dataStreamSpreadReductionFactorKey(token), dataStreamSpreadReductionFactor);\\n\\n _scheduleBatch(dataStore, payloads, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"feedId\\\", feedId);\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"dataStreamMultiplier\\\", dataStreamMultiplier);\\n eventData.uintItems.setItem(1, \\\"dataStreamSpreadReductionFactor\\\", dataStreamSpreadReductionFactor);\\n _signalPendingAction(\\n \\\"SignalSetDataStream\\\",\\n eventData\\n );\\n }\\n\\n // @dev increase the timelock delay\\n // @param the new timelock delay\\n function increaseTimelockDelay(uint256 _timelockDelay, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n if (_timelockDelay <= timelockController.getMinDelay()) {\\n revert Errors.InvalidTimelockDelay(_timelockDelay);\\n }\\n\\n if (_timelockDelay > MAX_TIMELOCK_DELAY) {\\n revert Errors.MaxTimelockDelayExceeded(_timelockDelay);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\\"updateDelay(uint256)\\\", _timelockDelay);\\n _schedule(address(timelockController), payload, predecessor, salt);\\n EventUtils.EventLogData memory eventData;\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"timelockDelay\\\", _timelockDelay);\\n _signalPendingAction(\\n \\\"IncreaseTimelockDelay\\\",\\n eventData\\n );\\n }\\n\\n function signalReduceLentAmount(\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (market == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n if (fundingAccount == address(0)) {\\n revert Errors.EmptyFundingAccount();\\n }\\n if (reductionAmount == 0) {\\n revert Errors.EmptyReduceLentAmount();\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"reduceLentImpactAmount(address,address,uint256)\\\",\\n market, fundingAccount, reductionAmount);\\n _schedule(address(timelockController), payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"reductionAmount\\\", reductionAmount);\\n _signalPendingAction(\\n \\\"SignalReduceLentImpactAmount\\\",\\n eventData\\n );\\n }\\n\\n // @dev Withdraw funds from position impact pool(negative price impacts) and send them to `receiver`\\n // @param market Market from withdraw\\n // @param receiver Account to send funds from pool\\n // @param amount Amount of tokens to withdraw\\n function signalWithdrawFromPositionImpactPool(\\n address market,\\n address receiver,\\n uint256 amount,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (market == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n if (amount == 0) {\\n revert Errors.EmptyPositionImpactWithdrawalAmount();\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"withdrawFromPositionImpactPool(address,address,uint256)\\\",\\n market, receiver, amount);\\n _schedule(address(timelockController), payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n _signalPendingAction(\\n \\\"SignalWithdrawFromPositionImpactPool\\\",\\n eventData\\n );\\n }\\n\\n function signalWithdrawTokens(\\n address target,\\n address token,\\n address receiver,\\n uint256 amount,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (target == address(0)) {\\n revert Errors.EmptyTarget();\\n }\\n if (token == address(0)) {\\n revert Errors.EmptyToken();\\n }\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n if (amount == 0) {\\n revert Errors.EmptyWithdrawalAmount();\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"withdrawTokens(address,address,uint256)\\\",\\n token,\\n receiver,\\n amount\\n );\\n _schedule(target, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"target\\\", target);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n _signalPendingAction(\\\"SignalWithdrawTokens\\\", eventData);\\n }\\n\\n function signalSetEdgeDataStream(\\n address token,\\n bytes32 edgeDataStreamId,\\n uint256 edgeDataStreamTokenDecimals,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (edgeDataStreamId == bytes32(0)) {\\n revert Errors.EmptyDataStreamFeedId(token);\\n }\\n\\n bytes[] memory payloads = new bytes[](2);\\n payloads[0] = abi.encodeWithSignature(\\\"setBytes32(bytes32,bytes32)\\\",\\n Keys.edgeDataStreamIdKey(token), edgeDataStreamId);\\n payloads[1] = abi.encodeWithSignature(\\\"setUint(bytes32,uint256)\\\",\\n Keys.edgeDataStreamTokenDecimalsKey(token), edgeDataStreamTokenDecimals);\\n\\n _scheduleBatch(dataStore, payloads, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"edgeDataStreamId\\\", edgeDataStreamId);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"edgeDataStreamTokenDecimals\\\", edgeDataStreamTokenDecimals);\\n\\n _signalPendingAction(\\\"SignalSetEdgeDataStream\\\", eventData);\\n }\\n\\n function signalSetMinContributorPaymentInterval(\\n address target,\\n uint256 interval,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (target == address(0)) {\\n revert Errors.EmptyTarget();\\n }\\n if (interval < 20 days) {\\n revert Errors.MinContributorPaymentIntervalBelowAllowedRange(interval);\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"setMinContributorPaymentInterval(uint256)\\\",\\n interval\\n );\\n _schedule(target, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"interval\\\", interval);\\n\\n _signalPendingAction(\\\"SignalSetMinContributorPaymentInterval\\\", eventData);\\n }\\n\\n function signalSetMaxTotalContributorTokenAmount(\\n address target,\\n address[] calldata tokens,\\n uint256[] calldata amounts,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n if (target == address(0)) {\\n revert Errors.EmptyTarget();\\n }\\n if (tokens.length != amounts.length) {\\n revert Errors.InvalidSetMaxTotalContributorTokenAmountInput(tokens.length, amounts.length);\\n }\\n for (uint256 i; i < tokens.length; i++) {\\n address token = tokens[i];\\n if (!DataStore(dataStore).containsAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token)) {\\n revert Errors.InvalidContributorToken(token);\\n }\\n }\\n\\n bytes memory payload = abi.encodeWithSignature(\\n \\\"setMaxTotalContributorTokenAmount(address[],uint256[])\\\",\\n tokens,\\n amounts\\n );\\n _schedule(target, payload, predecessor, salt);\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initArrayItems(1);\\n eventData.addressItems.setItem(0, \\\"tokens\\\", tokens);\\n\\n eventData.uintItems.initArrayItems(1);\\n eventData.uintItems.setItem(0, \\\"amounts\\\", amounts);\\n\\n _signalPendingAction(\\\"SignalSetMaxTotalContributorTokenAmount\\\", eventData);\\n }\\n\\n function execute(address target, bytes calldata payload, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\\n timelockController.execute(target, 0, payload, predecessor, salt);\\n }\\n\\n function executeWithOraclePrice(\\n address target,\\n bytes calldata payload,\\n bytes32 predecessor,\\n bytes32 salt,\\n OracleUtils.SetPricesParams calldata oracleParams\\n ) external onlyTimelockAdmin {\\n timelockController.executeWithOraclePrices(\\n target, 0, payload, predecessor, salt, oracleParams\\n );\\n }\\n\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external onlyTimelockAdmin {\\n timelockController.executeBatch(targets, values, payloads, predecessor, salt);\\n }\\n\\n function getHash(address target, bytes calldata payload, bytes32 predecessor, bytes32 salt) external view returns (bytes32) {\\n return timelockController.hashOperation(target, 0, payload, predecessor, salt);\\n }\\n\\n function getHashBatch(\\n address[] calldata targets,\\n bytes[] calldata payloads,\\n uint256[] calldata values,\\n bytes32 predecessor,\\n bytes32 salt\\n ) external view returns (bytes32) {\\n return timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt);\\n }\\n\\n function cancelAction(bytes32 id) external onlyTimelockAdmin {\\n timelockController.cancel(id);\\n }\\n\\n function _schedule(\\n address target,\\n bytes memory payload,\\n bytes32 predecessor,\\n bytes32 salt\\n ) internal {\\n timelockController.schedule(target, 0, payload, predecessor, salt, timelockController.getMinDelay());\\n }\\n\\n function _scheduleBatch(\\n address target,\\n bytes[] memory payloads,\\n bytes32 predecessor,\\n bytes32 salt\\n ) internal {\\n uint256 payloadCount = payloads.length;\\n address[] memory targets = new address[](payloadCount);\\n for (uint256 i; i < payloadCount; i++) {\\n targets[i] = target;\\n }\\n uint256[] memory values = new uint256[](payloadCount);\\n timelockController.scheduleBatch(\\n targets,\\n values,\\n payloads,\\n predecessor,\\n salt,\\n timelockController.getMinDelay()\\n );\\n }\\n\\n function _signalPendingAction(string memory actionLabel, EventUtils.EventLogData memory eventData) internal {\\n EventUtils.EventLogData memory actionData;\\n\\n bytes32 actionKey = keccak256(abi.encode(actionLabel));\\n\\n actionData.bytes32Items.initItems(1);\\n actionData.bytes32Items.setItem(0, \\\"actionKey\\\", actionKey);\\n\\n actionData.stringItems.initItems(1);\\n actionData.stringItems.setItem(0, \\\"actionLabel\\\", actionLabel);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignalPendingAction\\\",\\n actionKey,\\n actionData\\n );\\n\\n eventEmitter.emitEventLog(\\n actionLabel,\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xd044cecdcf6247e0f1e6f037ac3a751730c7db2e885a17c5b824fea0ba0d1609\",\"license\":\"BUSL-1.1\"},\"contracts/data/DataStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\n// @title DataStore\\n// @dev DataStore for all general state values\\ncontract DataStore is RoleModule {\\n using SafeCast for int256;\\n\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.UintSet;\\n\\n // store for uint values\\n mapping(bytes32 => uint256) public uintValues;\\n // store for int values\\n mapping(bytes32 => int256) public intValues;\\n // store for address values\\n mapping(bytes32 => address) public addressValues;\\n // store for bool values\\n mapping(bytes32 => bool) public boolValues;\\n // store for string values\\n mapping(bytes32 => string) public stringValues;\\n // store for bytes32 values\\n mapping(bytes32 => bytes32) public bytes32Values;\\n\\n // store for uint[] values\\n mapping(bytes32 => uint256[]) public uintArrayValues;\\n // store for int[] values\\n mapping(bytes32 => int256[]) public intArrayValues;\\n // store for address[] values\\n mapping(bytes32 => address[]) public addressArrayValues;\\n // store for bool[] values\\n mapping(bytes32 => bool[]) public boolArrayValues;\\n // store for string[] values\\n mapping(bytes32 => string[]) public stringArrayValues;\\n // store for bytes32[] values\\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\\n\\n // store for bytes32 sets\\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\\n // store for address sets\\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\\n // store for uint256 sets\\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev get the uint value for the given key\\n // @param key the key of the value\\n // @return the uint value for the key\\n function getUint(bytes32 key) external view returns (uint256) {\\n return uintValues[key];\\n }\\n\\n // @dev set the uint value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the uint value for the key\\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uintValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the uint value for the given key\\n // @param key the key of the value\\n function removeUint(bytes32 key) external onlyController {\\n delete uintValues[key];\\n }\\n\\n // @dev add the input int value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > currValue) {\\n revert(errorMessage);\\n }\\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 currValue = uintValues[key];\\n uint256 nextUint = currValue + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input int value to the existing uint value, prevent the uint\\n // value from becoming negative\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new uint value\\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\\n uint256 uintValue = uintValues[key];\\n if (value < 0 && (-value).toUint256() > uintValue) {\\n uintValues[key] = 0;\\n return 0;\\n }\\n\\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev add the input uint value to the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] + value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev subtract the input uint value from the existing uint value\\n // @param key the key of the value\\n // @param value the input uint value\\n // @return the new uint value\\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\\n uint256 nextUint = uintValues[key] - value;\\n uintValues[key] = nextUint;\\n return nextUint;\\n }\\n\\n // @dev get the int value for the given key\\n // @param key the key of the value\\n // @return the int value for the key\\n function getInt(bytes32 key) external view returns (int256) {\\n return intValues[key];\\n }\\n\\n // @dev set the int value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the int value for the key\\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n intValues[key] = value;\\n return value;\\n }\\n\\n function removeInt(bytes32 key) external onlyController {\\n delete intValues[key];\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev add the input int value to the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] + value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev subtract the input int value from the existing int value\\n // @param key the key of the value\\n // @param value the input int value\\n // @return the new int value\\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\\n int256 nextInt = intValues[key] - value;\\n intValues[key] = nextInt;\\n return nextInt;\\n }\\n\\n // @dev get the address value for the given key\\n // @param key the key of the value\\n // @return the address value for the key\\n function getAddress(bytes32 key) external view returns (address) {\\n return addressValues[key];\\n }\\n\\n // @dev set the address value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the address value for the key\\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\\n addressValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the address value for the given key\\n // @param key the key of the value\\n function removeAddress(bytes32 key) external onlyController {\\n delete addressValues[key];\\n }\\n\\n // @dev get the bool value for the given key\\n // @param key the key of the value\\n // @return the bool value for the key\\n function getBool(bytes32 key) external view returns (bool) {\\n return boolValues[key];\\n }\\n\\n // @dev set the bool value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bool value for the key\\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\\n boolValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bool value for the given key\\n // @param key the key of the value\\n function removeBool(bytes32 key) external onlyController {\\n delete boolValues[key];\\n }\\n\\n // @dev get the string value for the given key\\n // @param key the key of the value\\n // @return the string value for the key\\n function getString(bytes32 key) external view returns (string memory) {\\n return stringValues[key];\\n }\\n\\n // @dev set the string value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the string value for the key\\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\\n stringValues[key] = value;\\n return value;\\n }\\n\\n // @dev delete the string value for the given key\\n // @param key the key of the value\\n function removeString(bytes32 key) external onlyController {\\n delete stringValues[key];\\n }\\n\\n // @dev get the bytes32 value for the given key\\n // @param key the key of the value\\n // @return the bytes32 value for the key\\n function getBytes32(bytes32 key) external view returns (bytes32) {\\n return bytes32Values[key];\\n }\\n\\n // @dev set the bytes32 value for the given key\\n // @param key the key of the value\\n // @param value the value to set\\n // @return the bytes32 value for the key\\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\\n bytes32Values[key] = value;\\n return value;\\n }\\n\\n // @dev delete the bytes32 value for the given key\\n // @param key the key of the value\\n function removeBytes32(bytes32 key) external onlyController {\\n delete bytes32Values[key];\\n }\\n\\n // @dev get the uint array for the given key\\n // @param key the key of the uint array\\n // @return the uint array for the key\\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\\n return uintArrayValues[key];\\n }\\n\\n // @dev set the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\\n uintArrayValues[key] = value;\\n }\\n\\n // @dev delete the uint array for the given key\\n // @param key the key of the uint array\\n // @param value the value of the uint array\\n function removeUintArray(bytes32 key) external onlyController {\\n delete uintArrayValues[key];\\n }\\n\\n // @dev get the int array for the given key\\n // @param key the key of the int array\\n // @return the int array for the key\\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\\n return intArrayValues[key];\\n }\\n\\n // @dev set the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\\n intArrayValues[key] = value;\\n }\\n\\n // @dev delete the int array for the given key\\n // @param key the key of the int array\\n // @param value the value of the int array\\n function removeIntArray(bytes32 key) external onlyController {\\n delete intArrayValues[key];\\n }\\n\\n // @dev get the address array for the given key\\n // @param key the key of the address array\\n // @return the address array for the key\\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\\n return addressArrayValues[key];\\n }\\n\\n // @dev set the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\\n addressArrayValues[key] = value;\\n }\\n\\n // @dev delete the address array for the given key\\n // @param key the key of the address array\\n // @param value the value of the address array\\n function removeAddressArray(bytes32 key) external onlyController {\\n delete addressArrayValues[key];\\n }\\n\\n // @dev get the bool array for the given key\\n // @param key the key of the bool array\\n // @return the bool array for the key\\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\\n return boolArrayValues[key];\\n }\\n\\n // @dev set the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\\n boolArrayValues[key] = value;\\n }\\n\\n // @dev delete the bool array for the given key\\n // @param key the key of the bool array\\n // @param value the value of the bool array\\n function removeBoolArray(bytes32 key) external onlyController {\\n delete boolArrayValues[key];\\n }\\n\\n // @dev get the string array for the given key\\n // @param key the key of the string array\\n // @return the string array for the key\\n function getStringArray(bytes32 key) external view returns (string[] memory) {\\n return stringArrayValues[key];\\n }\\n\\n // @dev set the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\\n stringArrayValues[key] = value;\\n }\\n\\n // @dev delete the string array for the given key\\n // @param key the key of the string array\\n // @param value the value of the string array\\n function removeStringArray(bytes32 key) external onlyController {\\n delete stringArrayValues[key];\\n }\\n\\n // @dev get the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @return the bytes32 array for the key\\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\\n return bytes32ArrayValues[key];\\n }\\n\\n // @dev set the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\\n bytes32ArrayValues[key] = value;\\n }\\n\\n // @dev delete the bytes32 array for the given key\\n // @param key the key of the bytes32 array\\n // @param value the value of the bytes32 array\\n function removeBytes32Array(bytes32 key) external onlyController {\\n delete bytes32ArrayValues[key];\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\\n return bytes32Sets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\\n return bytes32Sets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return bytes32Sets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\\n bytes32Sets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\\n return addressSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\\n return addressSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return addressSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeAddress(bytes32 setKey, address value) external onlyController {\\n addressSets[setKey].remove(value);\\n }\\n\\n // @dev check whether the given value exists in the set\\n // @param setKey the key of the set\\n // @param value the value to check\\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\\n return uintSets[setKey].contains(value);\\n }\\n\\n // @dev get the length of the set\\n // @param setKey the key of the set\\n function getUintCount(bytes32 setKey) external view returns (uint256) {\\n return uintSets[setKey].length();\\n }\\n\\n // @dev get the values of the set in the given range\\n // @param setKey the key of the set\\n // @param the start of the range, values at the start index will be returned\\n // in the result\\n // @param the end of the range, values at the end index will not be returned\\n // in the result\\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\\n return uintSets[setKey].valuesAt(start, end);\\n }\\n\\n // @dev add the given value to the set\\n // @param setKey the key of the set\\n // @param value the value to add\\n function addUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].add(value);\\n }\\n\\n // @dev remove the given value from the set\\n // @param setKey the key of the set\\n // @param value the value to remove\\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\\n uintSets[setKey].remove(value);\\n }\\n}\\n\",\"keccak256\":\"0x38684fbf5eaa5e5c4ae0d220b28b7ceb3ddd6be8d983f162ac4430e7479dd90c\",\"license\":\"BUSL-1.1\"},\"contracts/data/Keys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Keys\\n// @dev Keys for values in the DataStore\\nlibrary Keys {\\n // @dev key for the address of the wrapped native token\\n bytes32 public constant WNT = keccak256(abi.encode(\\\"WNT\\\"));\\n // @dev key for the nonce value used in NonceUtils\\n bytes32 public constant NONCE = keccak256(abi.encode(\\\"NONCE\\\"));\\n\\n // @dev for sending received fees\\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\\\"FEE_RECEIVER\\\"));\\n\\n // @dev for holding tokens that could not be sent out\\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\\\"HOLDING_ADDRESS\\\"));\\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\\\"RELAY_FEE_ADDRESS\\\"));\\n\\n // @dev key for the minimum gas for execution error\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS\\\"));\\n\\n // @dev key for the minimum gas that should be forwarded for execution error handling\\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\\\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\\\"));\\n\\n // @dev key for the min additional gas for execution\\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\\\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\\\"));\\n\\n // @dev for a global reentrancy guard\\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\\\"REENTRANCY_GUARD_STATUS\\\"));\\n\\n // @dev key for deposit fees\\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for withdrawal fees\\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for swap fees\\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\\\"SWAP_FEE_TYPE\\\"));\\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_TYPE\\\"));\\n // @dev key for position fees\\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\\\"POSITION_FEE_TYPE\\\"));\\n // @dev key for ui deposit fees\\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\\\"UI_DEPOSIT_FEE_TYPE\\\"));\\n // @dev key for ui withdrawal fees\\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\\\"UI_WITHDRAWAL_FEE_TYPE\\\"));\\n // @dev key for ui swap fees\\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\\\"UI_SWAP_FEE_TYPE\\\"));\\n // @dev key for ui position fees\\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\\\"UI_POSITION_FEE_TYPE\\\"));\\n\\n // @dev key for ui fee factor\\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\\\"UI_FEE_FACTOR\\\"));\\n // @dev key for max ui fee receiver factor\\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\\\"MAX_UI_FEE_FACTOR\\\"));\\n\\n // @dev key for the claimable fee amount\\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FEE_AMOUNT\\\"));\\n // @dev key for the claimable ui fee amount\\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_UI_FEE_AMOUNT\\\"));\\n // @dev key for the max number of auto cancel orders\\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_AUTO_CANCEL_ORDERS\\\"));\\n // @dev key for the max total callback gas limit for auto cancel orders\\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\\\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\\\"));\\n\\n // @dev key for the market list\\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\\\"MARKET_LIST\\\"));\\n\\n // @dev key for the fee batch list\\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\\\"FEE_BATCH_LIST\\\"));\\n\\n // @dev key for the deposit list\\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\\\"DEPOSIT_LIST\\\"));\\n // @dev key for the account deposit list\\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_DEPOSIT_LIST\\\"));\\n\\n // @dev key for the withdrawal list\\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\\\"WITHDRAWAL_LIST\\\"));\\n // @dev key for the account withdrawal list\\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_WITHDRAWAL_LIST\\\"));\\n\\n // @dev key for the shift list\\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\\\"SHIFT_LIST\\\"));\\n // @dev key for the account shift list\\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\\\"ACCOUNT_SHIFT_LIST\\\"));\\n\\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\\\"GLV_LIST\\\"));\\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\\\"GLV_SHIFT_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_DEPOSIT_LIST\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\\\"ACCOUNT_GLV_WITHDRAWAL_LIST\\\"));\\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\\\"GLV_SUPPORTED_MARKET_LIST\\\"));\\n\\n // @dev key for the position list\\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\\\"POSITION_LIST\\\"));\\n // @dev key for the account position list\\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\\\"ACCOUNT_POSITION_LIST\\\"));\\n\\n // @dev key for the order list\\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\\\"ORDER_LIST\\\"));\\n // @dev key for the account order list\\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\\\"ACCOUNT_ORDER_LIST\\\"));\\n\\n // @dev key for the subaccount list\\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\\\"SUBACCOUNT_LIST\\\"));\\n\\n // @dev key for the auto cancel order list\\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\\\"AUTO_CANCEL_ORDER_LIST\\\"));\\n\\n // @dev key for is market disabled\\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_MARKET_DISABLED\\\"));\\n\\n // @dev key for the max swap path length allowed\\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\\\"MAX_SWAP_PATH_LENGTH\\\"));\\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\\\"SWAP_PATH_MARKET_FLAG\\\"));\\n // @dev key used to store the min market tokens for the first deposit for a market\\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create deposit feature is disabled\\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel deposit feature is disabled\\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_DEPOSIT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute deposit feature is disabled\\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_DEPOSIT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create withdrawal feature is disabled\\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel withdrawal feature is disabled\\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute withdrawal feature is disabled\\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute atomic withdrawal feature is disabled\\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create shift feature is disabled\\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel shift feature is disabled\\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_SHIFT_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute shift feature is disabled\\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_SHIFT_FEATURE_DISABLED\\\"));\\n\\n // @dev key for whether the create order feature is disabled\\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CREATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute order feature is disabled\\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the execute adl feature is disabled\\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\\\"EXECUTE_ADL_FEATURE_DISABLED\\\"));\\n // @dev key for whether the update order feature is disabled\\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"UPDATE_ORDER_FEATURE_DISABLED\\\"));\\n // @dev key for whether the cancel order feature is disabled\\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\\\"CANCEL_ORDER_FEATURE_DISABLED\\\"));\\n\\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_COLLATERAL_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\\\"));\\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\\\"CLAIM_UI_FEES_FEATURE_DISABLED\\\"));\\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_FEATURE_DISABLED\\\"));\\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\\\"GASLESS_FEATURE_DISABLED\\\"));\\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\\\"GENERAL_CLAIM_FEATURE_DISABLED\\\"));\\n\\n // @dev key for the minimum required oracle signers for an oracle observation\\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\\\"MIN_ORACLE_SIGNERS\\\"));\\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\\\"MIN_ORACLE_BLOCK_CONFIRMATIONS\\\"));\\n // @dev key for the maximum usable oracle price age in seconds\\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum usable atomic oracle price age in seconds\\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\\\"MAX_ATOMIC_ORACLE_PRICE_AGE\\\"));\\n // @dev key for the maximum oracle timestamp range\\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\\\"MAX_ORACLE_TIMESTAMP_RANGE\\\"));\\n // @dev key for the maximum oracle price deviation factor from the ref price\\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\\\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\\\"));\\n // @dev key for whether an oracle provider is enabled\\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_ORACLE_PROVIDER_ENABLED\\\"));\\n // @dev key for whether an oracle provider can be used for atomic actions\\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\\\"IS_ATOMIC_ORACLE_PROVIDER\\\"));\\n // @dev key for oracle timestamp adjustment\\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\\\"ORACLE_TIMESTAMP_ADJUSTMENT\\\"));\\n // @dev key for oracle provider for token\\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\\\"ORACLE_PROVIDER_FOR_TOKEN\\\"));\\n // @dev key for oracle provider updated time\\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\\\"ORACLE_PROVIDER_UPDATED_AT\\\"));\\n // @dev key for oracle provider same value delay\\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\\\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\\\"));\\n // @dev key for the chainlink payment token\\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\\\"CHAINLINK_PAYMENT_TOKEN\\\"));\\n // @dev key for the sequencer grace duration\\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\\\"SEQUENCER_GRACE_DURATION\\\"));\\n\\n // @dev key for the percentage amount of position fees to be received\\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of liquidation fees to be received\\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of swap fees to be received\\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_RECEIVER_FACTOR\\\"));\\n // @dev key for the percentage amount of borrowing fees to be received\\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\\\"BORROWING_FEE_RECEIVER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when estimating execution fee\\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the base gas limit used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\\\"));\\n // @dev key for the gas limit used for each oracle price\\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\\\"));\\n // @dev key for the multiplier used when calculating execution fee\\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n // @dev key for the max execution fee multiplier\\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\\\"));\\n\\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\\\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\\\"));\\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\\\"GELATO_RELAY_FEE_BASE_AMOUNT\\\"));\\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_DEPOSIT_GAS_LIMIT\\\"));\\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_WITHDRAWAL_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\\\"GLV_PER_MARKET_GAS_LIMIT\\\"));\\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\\\"SHIFT_GAS_LIMIT\\\"));\\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\\\"SINGLE_SWAP_GAS_LIMIT\\\"));\\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"INCREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"DECREASE_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\\\"SWAP_ORDER_GAS_LIMIT\\\"));\\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\\\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\\\"));\\n\\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\\\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\\\"));\\n\\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\\\"REQUEST_EXPIRATION_TIME\\\"));\\n\\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\\\"MAX_CALLBACK_GAS_LIMIT\\\"));\\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\\\"REFUND_EXECUTION_FEE_GAS_LIMIT\\\"));\\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\\\"SAVED_CALLBACK_CONTRACT\\\"));\\n\\n // @dev key for the min collateral factor\\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR\\\"));\\n // @dev key for the min collateral factor for open interest multiplier\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\\\"));\\n // @dev key for the min allowed collateral in USD\\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\\\"MIN_COLLATERAL_USD\\\"));\\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\\\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\\\"));\\n // @dev key for the min allowed position size in USD\\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\\\"MIN_POSITION_SIZE_USD\\\"));\\n\\n // @dev key for the virtual id of tokens\\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\\\"VIRTUAL_TOKEN_ID\\\"));\\n // @dev key for the virtual id of markets\\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\\\"VIRTUAL_MARKET_ID\\\"));\\n // @dev key for the virtual inventory for swaps\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_SWAPS\\\"));\\n // @dev key for the virtual inventory for positions\\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\\\"VIRTUAL_INVENTORY_FOR_POSITIONS\\\"));\\n\\n // @dev key for the position impact factor\\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the position impact exponent factor\\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"POSITION_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the max decrease position impact factor\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR\\\"));\\n // @dev key for the max position impact factor for liquidations\\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\\\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\\\"));\\n // @dev key for the position fee factor\\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\\\"POSITION_FEE_FACTOR\\\"));\\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\\\"PRO_TRADER_TIER\\\"));\\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\\\"PRO_DISCOUNT_FACTOR\\\"));\\n // @dev key for the liquidation fee factor\\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\\\"LIQUIDATION_FEE_FACTOR\\\"));\\n // @dev key for the swap impact factor\\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_FACTOR\\\"));\\n // @dev key for the swap impact exponent factor\\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\\\"SWAP_IMPACT_EXPONENT_FACTOR\\\"));\\n // @dev key for the swap fee factor\\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"SWAP_FEE_FACTOR\\\"));\\n // @dev key for the atomic swap fee factor\\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_SWAP_FEE_FACTOR\\\"));\\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"ATOMIC_WITHDRAWAL_FEE_FACTOR\\\"));\\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\\\"DEPOSIT_FEE_FACTOR\\\"));\\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\\\"WITHDRAWAL_FEE_FACTOR\\\"));\\n // @dev key for the oracle type\\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\\\"ORACLE_TYPE\\\"));\\n // @dev key for open interest\\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\\\"OPEN_INTEREST\\\"));\\n // @dev key for open interest in tokens\\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\\\"OPEN_INTEREST_IN_TOKENS\\\"));\\n // @dev key for collateral sum for a market\\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\\\"COLLATERAL_SUM\\\"));\\n // @dev key for pool amount\\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\\\"POOL_AMOUNT\\\"));\\n // @dev key for max pool amount\\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\\\"MAX_POOL_AMOUNT\\\"));\\n // @dev key for max pool usd for deposit\\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\\\"MAX_POOL_USD_FOR_DEPOSIT\\\"));\\n // @dev key for max open interest\\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\\\"MAX_OPEN_INTEREST\\\"));\\n // @dev key for position impact pool amount\\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for lent position impact pool amount\\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"LENT_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\\\"));\\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\\\"MAX_LENDABLE_IMPACT_USD\\\"));\\n // @dev key for total pending position impact amount\\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\\\"TOTAL_PENDING_IMPACT_AMOUNT\\\"));\\n // @dev key for min position impact pool amount\\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"MIN_POSITION_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for position impact pool distribution rate\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\\\"));\\n // @dev key for position impact pool distributed at\\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\\\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\\\"));\\n // @dev key for swap impact pool amount\\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\\\"SWAP_IMPACT_POOL_AMOUNT\\\"));\\n // @dev key for price feed\\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\\\"PRICE_FEED\\\"));\\n // @dev key for price feed multiplier\\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\\\"PRICE_FEED_MULTIPLIER\\\"));\\n // @dev key for price feed heartbeat\\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\\\"PRICE_FEED_HEARTBEAT_DURATION\\\"));\\n // @dev key for data stream feed id\\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\\\"DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_ID\\\"));\\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\\\"EDGE_DATA_STREAM_TOKEN_DECIMALS\\\"));\\n // @dev key for data stream feed multiplier\\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\\\"DATA_STREAM_MULTIPLIER\\\"));\\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\\\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\\\"));\\n // @dev key for stable price\\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\\\"STABLE_PRICE\\\"));\\n // @dev key for reserve factor\\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\\\"RESERVE_FACTOR\\\"));\\n // @dev key for open interest reserve factor\\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\\\"OPEN_INTEREST_RESERVE_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\\\"MAX_PNL_FACTOR\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_TRADERS\\\"));\\n // @dev key for max pnl factor for adl\\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_ADL\\\"));\\n // @dev key for min pnl factor for adl\\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\\\"MIN_PNL_FACTOR_AFTER_ADL\\\"));\\n // @dev key for max pnl factor\\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_DEPOSITS\\\"));\\n // @dev key for max pnl factor for withdrawals\\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\\\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\\\"));\\n // @dev key for latest ADL at\\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\\\"LATEST_ADL_AT\\\"));\\n // @dev key for whether ADL is enabled\\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\\\"IS_ADL_ENABLED\\\"));\\n // @dev key for funding factor\\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\\\"FUNDING_FACTOR\\\"));\\n // @dev key for funding exponent factor\\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"FUNDING_EXPONENT_FACTOR\\\"));\\n // @dev key for saved funding factor\\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"SAVED_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding increase factor\\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_INCREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for funding decrease factor\\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"FUNDING_DECREASE_FACTOR_PER_SECOND\\\"));\\n // @dev key for min funding factor\\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MIN_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for max funding factor\\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\\\"MAX_FUNDING_FACTOR_PER_SECOND\\\"));\\n // @dev key for threshold for stable funding\\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_STABLE_FUNDING\\\"));\\n // @dev key for threshold for decrease funding\\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\\\"THRESHOLD_FOR_DECREASE_FUNDING\\\"));\\n // @dev key for funding fee amount per size\\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"FUNDING_FEE_AMOUNT_PER_SIZE\\\"));\\n // @dev key for claimable funding amount per size\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\\\"));\\n // @dev key for when funding was last updated at\\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\\\"FUNDING_UPDATED_AT\\\"));\\n // @dev key for claimable funding amount\\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDING_AMOUNT\\\"));\\n // @dev key for claimable collateral amount\\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_AMOUNT\\\"));\\n // @dev key for claimable collateral factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_FACTOR\\\"));\\n // @dev key for claimable collateral reduction factor\\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\\\"));\\n // @dev key for claimable collateral time divisor\\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\\\"));\\n // @dev key for claimable collateral delay\\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\\\"CLAIMABLE_COLLATERAL_DELAY\\\"));\\n // @dev key for claimed collateral amount\\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\\\"CLAIMED_COLLATERAL_AMOUNT\\\"));\\n // @dev key for optimal usage factor\\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\\\"OPTIMAL_USAGE_FACTOR\\\"));\\n // @dev key for base borrowing factor\\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\\\"BASE_BORROWING_FACTOR\\\"));\\n // @dev key for above optimal usage borrowing factor\\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\\\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\\\"BORROWING_FACTOR\\\"));\\n // @dev key for borrowing factor\\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\\\"BORROWING_EXPONENT_FACTOR\\\"));\\n // @dev key for skipping the borrowing factor for the smaller side\\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\\\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\\\"));\\n // @dev key for cumulative borrowing factor\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR\\\"));\\n // @dev key for when the cumulative borrowing factor was last updated at\\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\\\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\\\"));\\n // @dev key for total borrowing amount\\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\\\"TOTAL_BORROWING\\\"));\\n // @dev key for affiliate reward\\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\\\"MIN_AFFILIATE_REWARD_FACTOR\\\"));\\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\\\"AFFILIATE_REWARD\\\"));\\n // @dev key for max allowed subaccount action count\\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\\\"));\\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\\\"SUBACCOUNT_EXPIRES_AT\\\"));\\n // @dev key for subaccount action count\\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\\\"SUBACCOUNT_ACTION_COUNT\\\"));\\n // @dev key for subaccount auto top up amount\\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\\\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\\\"));\\n // @dev key for subaccount order action\\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\\\"SUBACCOUNT_ORDER_ACTION\\\"));\\n // @dev key for subaccount integration id\\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_ID\\\"));\\n // @dev key for subaccount integration id disabled status\\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\\\"SUBACCOUNT_INTEGRATION_DISABLED\\\"));\\n // @dev key for fee distributor swap order token index\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\\\"));\\n // @dev key for fee distributor swap fee batch\\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\\\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\\\"));\\n\\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_COUNT\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\\\"));\\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\\\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\\\"));\\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\\\"IS_GLV_MARKET_DISABLED\\\"));\\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\\\"));\\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\\\"GLV_SHIFT_LAST_EXECUTED_AT\\\"));\\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\\\"GLV_SHIFT_MIN_INTERVAL\\\"));\\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\\\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\\\"));\\n\\n // @dev key for disabling automatic parameter updates via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_FEATURE_DISABLED\\\"));\\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_PARAMETER_DISABLED\\\"));\\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\\\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\\\"));\\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\\\"SYNC_CONFIG_UPDATE_COMPLETED\\\"));\\n // @dev key for the latest updateId that has been applied by ConfigSyncer\\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\\\"SYNC_CONFIG_LATEST_UPDATE_ID\\\"));\\n\\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_ACCOUNT_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_LIST\\\"));\\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\\\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\\\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\\\"));\\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\\\"CONTRIBUTOR_LAST_PAYMENT_AT\\\"));\\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\\\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\\\"));\\n\\n // @dev key for the buyback batch amount used when claiming and swapping fees\\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_BATCH_AMOUNT\\\"));\\n // @dev key for the buyback available fees\\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\\\"BUYBACK_AVAILABLE_FEE_AMOUNT\\\"));\\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\\\"BUYBACK_GMX_FACTOR\\\"));\\n // @dev key for the FeeHandler max price impact when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\\\"));\\n // @dev key for the maximum price delay in seconds when buying back fees\\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\\\"BUYBACK_MAX_PRICE_AGE\\\"));\\n // @dev key for the buyback withdrawable fees\\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\\\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\\\"));\\n\\n // @dev key for user's multichain balance\\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\\\"MULTICHAIN_BALANCE\\\"));\\n // @dev key for the flag if a multichain provider is enabled\\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_PROVIDER_ENABLED\\\"));\\n // @dev key for the flag if a multichain endpoint is enabled\\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\\\"IS_MULTICHAIN_ENDPOINT_ENABLED\\\"));\\n // @dev key for the flag if the relay fee is excluded for the caller\\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\\\"IS_RELAY_FEE_EXCLUDED\\\"));\\n // @dev key for the flag if a src chain is enabled\\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\\\"IS_SRC_CHAIN_ID_ENABLED\\\"));\\n // @dev key for the last src chain id from which the user last managed his position\\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\\\"POSITION_LAST_SRC_CHAIN_ID\\\"));\\n // @dev key for the source chain id mapped from the endpoint id\\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\\\"EID_TO_SRC_CHAIN_ID\\\"));\\n\\n // @dev key for the maximum length for data list array of bytes32\\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\\\"MAX_DATA_LENGTH\\\"));\\n // @dev key for the action data\\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\\\"GMX_DATA_ACTION\\\"));\\n // @dev key for the claimable fund amount for a specific account and token\\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the total claimable amount for a specific token\\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\\\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\\\"));\\n // @dev key for the terms for a specific distribution\\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\\\"CLAIM_TERMS\\\"));\\n // @dev key for the terms hash for a specific distribution\\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\\\"CLAIM_TERMS_BACKREF\\\"));\\n\\n // @dev constant for user initiated cancel reason\\n string public constant USER_INITIATED_CANCEL = \\\"USER_INITIATED_CANCEL\\\";\\n\\n // @dev function used to calculate fullKey for a given market parameter\\n // @param baseKey the base key for the market parameter\\n // @param data the additional data for the market parameter\\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\\n if (data.length == 0) {\\n return baseKey;\\n }\\n\\n return keccak256(bytes.concat(baseKey, data));\\n }\\n\\n // @dev key for the account deposit list\\n // @param account the account for the list\\n function accountDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account withdrawal list\\n // @param account the account for the list\\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the account shift list\\n // @param account the account for the list\\n function accountShiftListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\\n }\\n\\n // @dev key for the account glv deposit list\\n // @param account the account for the list\\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\\n }\\n\\n // @dev key for the glv supported market list\\n // @param glv the glv for the supported market list\\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\\n }\\n\\n // @dev key for the account position list\\n // @param account the account for the list\\n function accountPositionListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\\n }\\n\\n // @dev key for the account order list\\n // @param account the account for the list\\n function accountOrderListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\\n }\\n\\n // @dev key for the subaccount list\\n // @param account the account for the list\\n function subaccountListKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\\n }\\n\\n // @dev key for the auto cancel order list\\n // @param position key the position key for the list\\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\\n }\\n\\n // @dev key for the claimable fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\\n }\\n\\n // @dev key for the claimable ui fee amount for account\\n // @param market the market for the fee\\n // @param token the token for the fee\\n // @param account the account that can claim the ui fee\\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\\n }\\n\\n // @dev key for deposit gas limit\\n // @param singleToken whether a single token or pair tokens are being deposited\\n // @return key for deposit gas limit\\n function depositGasLimitKey() internal pure returns (bytes32) {\\n return DEPOSIT_GAS_LIMIT;\\n }\\n\\n // @dev key for withdrawal gas limit\\n // @return key for withdrawal gas limit\\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\\n return WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n // @dev key for shift gas limit\\n // @return key for shift gas limit\\n function shiftGasLimitKey() internal pure returns (bytes32) {\\n return SHIFT_GAS_LIMIT;\\n }\\n\\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\\n return GLV_DEPOSIT_GAS_LIMIT;\\n }\\n\\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\\n return GLV_WITHDRAWAL_GAS_LIMIT;\\n }\\n\\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\\n return GLV_SHIFT_GAS_LIMIT;\\n }\\n\\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\\n return GLV_PER_MARKET_GAS_LIMIT;\\n }\\n\\n // @dev key for single swap gas limit\\n // @return key for single swap gas limit\\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\\n return SINGLE_SWAP_GAS_LIMIT;\\n }\\n\\n // @dev key for increase order gas limit\\n // @return key for increase order gas limit\\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return INCREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for decrease order gas limit\\n // @return key for decrease order gas limit\\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\\n return DECREASE_ORDER_GAS_LIMIT;\\n }\\n\\n // @dev key for swap order gas limit\\n // @return key for swap order gas limit\\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\\n return SWAP_ORDER_GAS_LIMIT;\\n }\\n\\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_PATH_MARKET_FLAG,\\n market\\n ));\\n }\\n\\n // @dev key for whether create glv deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create glv withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel glv withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute glv withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n\\n // @dev key for whether create deposit is disabled\\n // @param the create deposit module\\n // @return key for whether create deposit is disabled\\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel deposit is disabled\\n // @param the cancel deposit module\\n // @return key for whether cancel deposit is disabled\\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute deposit is disabled\\n // @param the execute deposit module\\n // @return key for whether execute deposit is disabled\\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create withdrawal is disabled\\n // @param the create withdrawal module\\n // @return key for whether create withdrawal is disabled\\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel withdrawal is disabled\\n // @param the cancel withdrawal module\\n // @return key for whether cancel withdrawal is disabled\\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute withdrawal is disabled\\n // @param the execute withdrawal module\\n // @return key for whether execute withdrawal is disabled\\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute atomic withdrawal is disabled\\n // @param the execute atomic withdrawal module\\n // @return key for whether execute atomic withdrawal is disabled\\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create shift is disabled\\n // @param the create shift module\\n // @return key for whether create shift is disabled\\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether cancel shift is disabled\\n // @param the cancel shift module\\n // @return key for whether cancel shift is disabled\\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether execute shift is disabled\\n // @param the execute shift module\\n // @return key for whether execute shift is disabled\\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_SHIFT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether create order is disabled\\n // @param the create order module\\n // @return key for whether create order is disabled\\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CREATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute order is disabled\\n // @param the execute order module\\n // @return key for whether execute order is disabled\\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether execute adl is disabled\\n // @param the execute adl module\\n // @return key for whether execute adl is disabled\\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EXECUTE_ADL_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether update order is disabled\\n // @param the update order module\\n // @return key for whether update order is disabled\\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UPDATE_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether cancel order is disabled\\n // @param the cancel order module\\n // @return key for whether cancel order is disabled\\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CANCEL_ORDER_FEATURE_DISABLED,\\n module,\\n orderType\\n ));\\n }\\n\\n // @dev key for whether claim funding fees is disabled\\n // @param the claim funding fees module\\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim colltareral is disabled\\n // @param the claim funding fees module\\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_COLLATERAL_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim affiliate rewards is disabled\\n // @param the claim affiliate rewards module\\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether claim ui fees is disabled\\n // @param the claim ui fees module\\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_UI_FEES_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the subaccount module\\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether subaccounts are disabled\\n // @param the gasless module\\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GASLESS_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GENERAL_CLAIM_FEATURE_DISABLED,\\n distributionId\\n ));\\n }\\n\\n // @dev key for ui fee factor\\n // @param account the fee receiver account\\n // @return key for ui fee factor\\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n UI_FEE_FACTOR,\\n account\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is enabled\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is enabled\\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ORACLE_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\\n // @param provider the oracle provider\\n // @return key for whether an oracle provider is allowed to be used for atomic actions\\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ATOMIC_ORACLE_PROVIDER,\\n provider\\n ));\\n }\\n\\n // @dev key for oracle timestamp adjustment\\n // @param provider the oracle provider\\n // @param token the token\\n // @return key for oracle timestamp adjustment\\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TIMESTAMP_ADJUSTMENT,\\n provider,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider for token\\n // @param token the token\\n // @return key for oracle provider for token\\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_FOR_TOKEN,\\n oracle,\\n token\\n ));\\n }\\n\\n // @dev key for oracle provider update time\\n // @param token the token\\n // @param provider address\\n // @return key for oracle provider updated time\\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_PROVIDER_UPDATED_AT,\\n token,\\n provider\\n ));\\n }\\n\\n // @dev key for gas to forward for token transfer\\n // @param the token to check\\n // @return key for gas to forward for token transfer\\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOKEN_TRANSFER_GAS_LIMIT,\\n token\\n ));\\n }\\n\\n // @dev the default callback contract\\n // @param account the user's account\\n // @param market the address of the market\\n // @param callbackContract the callback contract\\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_CALLBACK_CONTRACT,\\n account,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor key\\n // @param the market for the min collateral factor\\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the min collateral factor for open interest multiplier key\\n // @param the market for the factor\\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual token id\\n // @param the token to get the virtual id for\\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_TOKEN_ID,\\n token\\n ));\\n }\\n\\n // @dev the key for the virtual market id\\n // @param the market to get the virtual id for\\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_MARKET_ID,\\n market\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for positions\\n // @param the virtualTokenId the virtual token id\\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_POSITIONS,\\n virtualTokenId\\n ));\\n }\\n\\n // @dev the key for the virtual inventory for swaps\\n // @param the virtualMarketId the virtual market id\\n // @param the token to check the inventory for\\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n VIRTUAL_INVENTORY_FOR_SWAPS,\\n virtualMarketId,\\n isLongToken\\n ));\\n }\\n\\n // @dev key for position impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for position impact factor\\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for position impact exponent factor\\n // @param market the market address to check\\n // @return key for position impact exponent factor\\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for the max position impact factor\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for the max position impact factor for liquidations\\n // @param market the market address to check\\n // @return key for the max position impact factor\\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\\n market\\n ));\\n }\\n\\n // @dev key for position fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for position fee factor\\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for pro trader's tier\\n function proTraderTierKey(address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_TRADER_TIER,\\n account\\n ));\\n }\\n\\n\\n // @dev key for pro discount factor for specific tier\\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRO_DISCOUNT_FACTOR,\\n proTier\\n ));\\n }\\n\\n // @dev key for liquidation fee factor\\n // @param market the market address to check\\n // @return key for liquidation fee factor\\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LIQUIDATION_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for swap impact factor\\n // @param market the market address to check\\n // @param isPositive whether the impact is positive or negative\\n // @return key for swap impact factor\\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_FACTOR,\\n market,\\n isPositive\\n ));\\n }\\n\\n // @dev key for swap impact exponent factor\\n // @param market the market address to check\\n // @return key for swap impact exponent factor\\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n\\n // @dev key for swap fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for swap fee factor\\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for atomic swap fee factor\\n // @param market the market address to check\\n // @return key for atomic swap fee factor\\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_SWAP_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for atomic withdrawal fee factor\\n // @param market the market address to check\\n // @return key for atomic withdrawal fee factor\\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev key for deposit fee factor\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for deposit fee factor\\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DEPOSIT_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for withdrawal fee factor\\n // @param market the market address to check\\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\\n // @return key for withdrawal fee factor\\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWAL_FEE_FACTOR,\\n market,\\n balanceWasImproved\\n ));\\n }\\n\\n // @dev key for oracle type\\n // @param token the token to check\\n // @return key for oracle type\\n function oracleTypeKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ORACLE_TYPE,\\n token\\n ));\\n }\\n\\n // @dev key for open interest\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest\\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest in tokens\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for open interest in tokens\\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_IN_TOKENS,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for collateral sum for a market\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short open interest\\n // @return key for collateral sum\\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n COLLATERAL_SUM,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's pool\\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max amount of pool tokens\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max usd of pool tokens for deposits\\n // @param market the market for the pool\\n // @param token the token for the pool\\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_POOL_USD_FOR_DEPOSIT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev the key for the max open interest\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_OPEN_INTEREST,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for amount of tokens in a market's position impact pool\\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LENT_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR,\\n market\\n ));\\n }\\n\\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\\n market\\n ));\\n }\\n\\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_LENDABLE_IMPACT_USD,\\n market\\n ));\\n }\\n\\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_PENDING_IMPACT_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for min amount of tokens in a market's position impact pool\\n // @param market the market to check\\n // @return key for min amount of tokens in a market's position impact pool\\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_POSITION_IMPACT_POOL_AMOUNT,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distribution rate\\n // @param market the market to check\\n // @return key for position impact pool distribution rate\\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\\n market\\n ));\\n }\\n\\n // @dev key for position impact pool distributed at\\n // @param market the market to check\\n // @return key for position impact pool distributed at\\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for amount of tokens in a market's swap impact pool\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for amount of tokens in a market's swap impact pool\\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SWAP_IMPACT_POOL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for reserve factor\\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for open interest reserve factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for open interest reserve factor\\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPEN_INTEREST_RESERVE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for max pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for max pnl factor\\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_PNL_FACTOR,\\n pnlFactorType,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for min PnL factor after ADL\\n // @param market the market for the pool\\n // @param isLong whether the key is for the long or short side\\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_PNL_FACTOR_AFTER_ADL,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for latest adl time\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for latest adl time\\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n LATEST_ADL_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for whether adl is enabled\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for whether adl is enabled\\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_ADL_ENABLED,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for funding factor\\n // @param market the market to check\\n // @return key for funding factor\\n function fundingFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for funding exponent\\n // @param market the market for the pool\\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_EXPONENT_FACTOR,\\n market\\n ));\\n }\\n\\n // @dev the key for saved funding factor\\n // @param market the market for the pool\\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SAVED_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding increase factor\\n // @param market the market for the pool\\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_INCREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for funding decrease factor\\n // @param market the market for the pool\\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_DECREASE_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for min funding factor\\n // @param market the market for the pool\\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for max funding factor\\n // @param market the market for the pool\\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_FUNDING_FACTOR_PER_SECOND,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for stable funding\\n // @param market the market for the pool\\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_STABLE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev the key for threshold for decreasing funding\\n // @param market the market for the pool\\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n THRESHOLD_FOR_DECREASE_FUNDING,\\n market\\n ));\\n }\\n\\n // @dev key for funding fee amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for funding fee amount per size\\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_FEE_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for claimabel funding amount per size\\n // @param market the market to check\\n // @param collateralToken the collateralToken to get the key for\\n // @param isLong whether to get the key for the long or short side\\n // @return key for claimable funding amount per size\\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\\n market,\\n collateralToken,\\n isLong\\n ));\\n }\\n\\n // @dev key for when funding was last updated\\n // @param market the market to check\\n // @return key for when funding was last updated\\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FUNDING_UPDATED_AT,\\n market\\n ));\\n }\\n\\n // @dev key for claimable funding amount\\n // @param market the market to check\\n // @param token the token to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable funding amount by account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDING_AMOUNT,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral amount\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token\\n ));\\n }\\n\\n // @dev key for claimable collateral amount for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey\\n ));\\n }\\n\\n // @dev key for claimable collateral factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable amount\\n // @param account the account to check\\n // @return key for claimable funding amount\\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral reduction factor for a timeKey for an account\\n // @param market the market to check\\n // @param token the token to check\\n // @param timeKey the time key for the claimable factor\\n // @param account the account to check\\n // @return key for claimable funding factor\\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for claimable collateral factor\\n // @param market the market to check\\n // @param token the token to check\\n // @param account the account to check\\n // @param timeKey the time key for the claimable amount\\n // @return key for claimable funding amount\\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMED_COLLATERAL_AMOUNT,\\n market,\\n token,\\n timeKey,\\n account\\n ));\\n }\\n\\n // @dev key for optimal usage factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for optimal usage factor\\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n OPTIMAL_USAGE_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for base borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for base borrowing factor\\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BASE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for above optimal usage borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for above optimal usage borrowing factor\\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for borrowing factor\\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev the key for borrowing exponent\\n // @param market the market for the pool\\n // @param isLong whether to get the key for the long or short side\\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BORROWING_EXPONENT_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor\\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for cumulative borrowing factor updated at\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for cumulative borrowing factor updated at\\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for total borrowing amount\\n // @param market the market to check\\n // @param isLong whether to get the key for the long or short side\\n // @return key for total borrowing amount\\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_BORROWING,\\n market,\\n isLong\\n ));\\n }\\n\\n // @dev key for affiliate reward amount\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token\\n ));\\n }\\n\\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_AFFILIATE_REWARD_FACTOR,\\n referralTierLevel\\n ));\\n }\\n\\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_EXPIRES_AT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_ACTION_COUNT,\\n account,\\n subaccount,\\n actionType\\n ));\\n }\\n\\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_ID,\\n account,\\n subaccount\\n ));\\n }\\n\\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SUBACCOUNT_INTEGRATION_DISABLED,\\n integrationId\\n ));\\n }\\n\\n // @dev key for affiliate reward amount for an account\\n // @param market the market to check\\n // @param token the token to get the key for\\n // @param account the account to get the key for\\n // @return key for affiliate reward amount\\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n AFFILIATE_REWARD,\\n market,\\n token,\\n account\\n ));\\n }\\n\\n // @dev key for is market disabled\\n // @param market the market to check\\n // @return key for is market disabled\\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for min market tokens for first deposit\\n // @param market the market to check\\n // @return key for min market tokens for first deposit\\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\\n market\\n ));\\n }\\n\\n // @dev key for price feed address\\n // @param token the token to get the key for\\n // @return key for price feed address\\n function priceFeedKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed ID\\n // @param token the token to get the key for\\n // @return key for data stream feed ID\\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_ID,\\n token\\n ));\\n }\\n\\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\\n token\\n ));\\n }\\n\\n // @dev key for data stream feed multiplier\\n // @param token the token to get the key for\\n // @return key for data stream feed multiplier\\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for price feed multiplier\\n // @param token the token to get the key for\\n // @return key for price feed multiplier\\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_MULTIPLIER,\\n token\\n ));\\n }\\n\\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n PRICE_FEED_HEARTBEAT_DURATION,\\n token\\n ));\\n }\\n\\n // @dev key for stable price value\\n // @param token the token to get the key for\\n // @return key for stable price value\\n function stablePriceKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n STABLE_PRICE,\\n token\\n ));\\n }\\n\\n // @dev key for fee distributor swap token index\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap token index\\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\\n orderKey\\n ));\\n }\\n\\n // @dev key for fee distributor swap fee batch key\\n // @param orderKey the swap order key\\n // @return key for fee distributor swap fee batch key\\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\\n orderKey\\n ));\\n }\\n\\n // @dev key for max market token balance usd\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\\n }\\n\\n // @dev key for max market token balance amount\\n // it is used to limit amount of funds deposited into each market\\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\\n }\\n\\n // @dev key for is glv market disabled\\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_GLV_MARKET_DISABLED,\\n glv,\\n market\\n ));\\n }\\n\\n // @dev key for max allowed price impact for glv shifts\\n // if effective price impact exceeds max price impact then glv shift fails\\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\\n glv\\n ));\\n }\\n\\n // @dev key for time when glv shift was executed last\\n // used to validate glv shifts are not executed too frequently\\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_LAST_EXECUTED_AT,\\n glv\\n ));\\n }\\n\\n // @dev key for min time interval between glv shifts in seconds\\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n GLV_SHIFT_MIN_INTERVAL,\\n glv\\n ));\\n }\\n\\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\\n glv\\n ));\\n }\\n\\n // @dev key for whether the sync config feature is disabled\\n // @param module the sync config module\\n // @return key for sync config feature disabled\\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_FEATURE_DISABLED,\\n module\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market\\n // @param market the market to check\\n // @return key for sync config market disabled\\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_DISABLED,\\n market\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a parameter\\n // @param parameter the parameter to check\\n // @return key for sync config parameter disabled\\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_PARAMETER_DISABLED,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether sync config updates are disabled for a market parameter\\n // @param market the market to check\\n // @param parameter the parameter to check\\n // @return key for sync config market parameter disabled\\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\\n market,\\n parameter\\n ));\\n }\\n\\n // @dev key for whether a sync config update is completed\\n // @param updateId the update id to check\\n // @return key for sync config market update completed\\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n SYNC_CONFIG_UPDATE_COMPLETED,\\n updateId\\n ));\\n }\\n\\n // @dev key for the latest sync config update that was completed\\n // @return key for sync config latest update id\\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\\n return SYNC_CONFIG_LATEST_UPDATE_ID;\\n }\\n\\n // @dev key for the contributor token amount\\n // @param account the contributor account\\n // @param token the contributor token\\n // @return key for the contributor token amount\\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_TOKEN_AMOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the max total contributor token amount\\n // @param token the contributor token\\n // @return key for the max contributor token amount\\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\\n token\\n ));\\n }\\n\\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CONTRIBUTOR_FUNDING_ACCOUNT,\\n token\\n ));\\n }\\n\\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback batch amount\\n // @param token the token for which to retrieve batch amount (GMX or WNT)\\n // @return key for buyback batch amount for a given token\\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_BATCH_AMOUNT,\\n token\\n ));\\n }\\n\\n // @dev key for the buyback available fee amount\\n // @param feeToken the token in which the fees are denominated\\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\\n // @return key for buyback available fee amount for a given token and feeToken\\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_AVAILABLE_FEE_AMOUNT,\\n feeToken,\\n swapToken\\n ));\\n }\\n\\n // @dev key for the buyback withdrawable fee amount\\n // @param buybackToken the token that was bought back\\n // @return key for the buyback withdrawable fee amount\\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\\n buybackToken\\n ));\\n }\\n\\n // @dev key for the buyback gmx fee factor\\n // @param version the version for which to retrieve the fee numerator\\n // @return key for buyback gmx fee factor for a given version\\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_GMX_FACTOR,\\n version\\n ));\\n }\\n\\n // @dev key for the buyback max price impact factor\\n // @param token the token for which to retrieve the max price impact factor key\\n // @return key for buyback max price impact factor for a given token\\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\\n token\\n ));\\n }\\n\\n // @dev key for whether a multichain provider is enabled\\n // @param provider the multichain provider\\n // @return key for whether a multichain provider is enabled\\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_PROVIDER_ENABLED,\\n provider\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_MULTICHAIN_ENDPOINT_ENABLED,\\n endpoint\\n ));\\n }\\n\\n // @dev key for whether a relay fee is excluded for the caller\\n // @param sender the address of the sender\\n // @return key for whether a relay fee is excluded\\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_RELAY_FEE_EXCLUDED,\\n sender\\n ));\\n }\\n\\n // @dev key for whether a multichain endpoint is enabled\\n // @param endpoint the multichain endpoint\\n // @return key for whether a multichain endpoint is enabled\\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n IS_SRC_CHAIN_ID_ENABLED,\\n srcChainId\\n ));\\n }\\n\\n // @dev key for the last src chain id from which the user last managed his position\\n // @param positionKey the position key for which to retrieve the last src chain id\\n // @return key for the last src chain id from which the user last managed his position\\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n POSITION_LAST_SRC_CHAIN_ID,\\n positionKey\\n ));\\n }\\n\\n // @dev key for the source chain id mapped from the endpoint id\\n // @param eid the endpoint id of the source chain\\n // @return key for the srcChainId\\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n EID_TO_SRC_CHAIN_ID,\\n eid\\n ));\\n }\\n\\n // @dev key for user's multichain balance\\n // @param account the account for which to retrieve the user balance key\\n // @param token the token for which to retrieve the user balance key\\n // @return key for multichain balance for a given user and token\\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n MULTICHAIN_BALANCE,\\n account,\\n token\\n ));\\n }\\n\\n // @dev key for the claimable fund amount for a specific account and token\\n // @param account the account to claim funds for\\n // @param token the token to claim\\n // @param distributionId the distribution id to claim funds for\\n // @return key for claimable fund amount\\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIMABLE_FUNDS_AMOUNT,\\n account,\\n token,\\n distributionId\\n ));\\n }\\n\\n // @dev key for the total claimable amount for a specific token\\n // @param token the token for which to retrieve the total claimable amount\\n // @return key for total claimable amount\\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\\n token\\n ));\\n }\\n\\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS,\\n distributionId\\n ));\\n }\\n\\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\\n return keccak256(abi.encode(\\n CLAIM_TERMS_BACKREF,\\n termsHash\\n ));\\n }\\n}\\n\",\"keccak256\":\"0x29d3b6a5d0646acf9be185cbce51ed40bc3005d172aab9a4ae9f21a6a040bb3f\",\"license\":\"BUSL-1.1\"},\"contracts/error/ErrorUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary ErrorUtils {\\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\\n // If the result length is less than 68, then the transaction either panicked or failed silently\\n if (result.length < 68) {\\n return (\\\"\\\", false);\\n }\\n\\n bytes4 errorSelector = getErrorSelectorFromData(result);\\n\\n // 0x08c379a0 is the selector for Error(string)\\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\\n if (errorSelector == bytes4(0x08c379a0)) {\\n assembly {\\n result := add(result, 0x04)\\n }\\n\\n return (abi.decode(result, (string)), true);\\n }\\n\\n // error may be a custom error, return an empty string for this case\\n return (\\\"\\\", false);\\n }\\n\\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\\n bytes4 errorSelector;\\n\\n assembly {\\n errorSelector := mload(add(data, 0x20))\\n }\\n\\n return errorSelector;\\n }\\n\\n function revertWithParsedMessage(bytes memory result) internal pure {\\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\\n\\n if (hasRevertMessage) {\\n revert(revertMessage);\\n } else {\\n revertWithCustomError(result);\\n }\\n }\\n\\n function revertWithCustomError(bytes memory result) internal pure {\\n // referenced from https://ethereum.stackexchange.com/a/123588\\n uint256 length = result.length;\\n assembly {\\n revert(add(result, 0x20), length)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8dad7020da39ccf5759e4d9cefeb8a943cab645ea96f3a27a4f6ce3168f3dcbc\",\"license\":\"BUSL-1.1\"},\"contracts/error/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary Errors {\\n // AdlHandler errors\\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\\n\\n // AdlUtils errors\\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error AdlNotEnabled();\\n\\n // AutoCancelUtils errors\\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\\n\\n // Bank errors\\n error SelfTransferNotSupported(address receiver);\\n error InvalidNativeTokenSender(address msgSender);\\n\\n // BaseHandler errors\\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\\n\\n // CallbackUtils errors\\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\\n\\n // Config errors\\n error InvalidBaseKey(bytes32 baseKey);\\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\\n error InvalidClaimableFactor(uint256 value);\\n error InvalidClaimableReductionFactor(uint256 value);\\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\\n error PriceFeedAlreadyExistsForToken(address token);\\n error DataStreamIdAlreadyExistsForToken(address token);\\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\\n error EmptyToken();\\n\\n // ContributorHandler errors\\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\\n error InvalidContributorToken(address token);\\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\\n\\n // Timelock errors\\n error ActionAlreadySignalled();\\n error ActionNotSignalled();\\n error SignalTimeNotYetPassed(uint256 signalTime);\\n error InvalidTimelockDelay(uint256 timelockDelay);\\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\\n error InvalidFeeReceiver(address receiver);\\n error InvalidOracleSigner(address signer);\\n error InvalidHoldingAddress(address account);\\n error EmptyPositionImpactWithdrawalAmount();\\n error OraclePriceOutdated();\\n error EmptyTarget();\\n error EmptyFundingAccount();\\n error EmptyReduceLentAmount();\\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\\n\\n // GlvDepositStoreUtils errors\\n error GlvDepositNotFound(bytes32 key);\\n // GlvShiftStoreUtils errors\\n error GlvShiftNotFound(bytes32 key);\\n // GlvWithdrawalStoreUtils errors\\n error GlvWithdrawalNotFound(bytes32 key);\\n // GlvDepositUtils errors\\n error EmptyGlvDepositAmounts();\\n error EmptyGlvMarketAmount();\\n error EmptyGlvDeposit();\\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\\n // GlvWithdrawalUtils errors\\n error EmptyGlvWithdrawal();\\n error EmptyGlvWithdrawalAmount();\\n // GlvUtils errors\\n error EmptyGlv(address glv);\\n error EmptyGlvTokenSupply();\\n error GlvNegativeMarketPoolValue(address glv, address market);\\n error GlvUnsupportedMarket(address glv, address market);\\n error GlvDisabledMarket(address glv, address market);\\n error GlvEnabledMarket(address glv, address market);\\n error GlvNonZeroMarketBalance(address glv, address market);\\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\\n error GlvMarketAlreadyExists(address glv, address market);\\n error GlvInvalidLongToken(address glv, address provided, address expected);\\n error GlvInvalidShortToken(address glv, address provided, address expected);\\n // GlvShiftUtils\\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\\n // GlvFactory\\n error GlvAlreadyExists(bytes32 salt, address glv);\\n error GlvSymbolTooLong();\\n error GlvNameTooLong();\\n // GlvStoreUtils\\n error GlvNotFound(address key);\\n\\n // DepositStoreUtils errors\\n error DepositNotFound(bytes32 key);\\n\\n // DepositUtils errors\\n error EmptyDeposit();\\n error EmptyDepositAmounts();\\n\\n // ExecuteDepositUtils errors\\n error MinMarketTokens(uint256 received, uint256 expected);\\n error EmptyDepositAmountsAfterSwap();\\n error InvalidPoolValueForDeposit(int256 poolValue);\\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\\n\\n // ExternalHandler errors\\n error ExternalCallFailed(bytes data);\\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\\n error InvalidExternalCallTarget(address target);\\n\\n // FeeBatchStoreUtils errors\\n error FeeBatchNotFound(bytes32 key);\\n\\n // FeeDistributor errors\\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\\n\\n // GlpMigrator errors\\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\\n\\n // GlvHandler errors\\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n error MinGlvTokens(uint256 received, uint256 expected);\\n\\n // OrderHandler errors\\n error OrderNotUpdatable(uint256 orderType);\\n error InvalidKeeperForFrozenOrder(address keeper);\\n\\n // FeatureUtils errors\\n error DisabledFeature(bytes32 key);\\n\\n // FeeHandler errors\\n error InvalidBuybackToken(address buybackToken);\\n error InvalidVersion(uint256 version);\\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\\n error EmptyClaimFeesMarket();\\n\\n // GasUtils errors\\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\\n error EmptyRelayFeeAddress();\\n\\n // MarketFactory errors\\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\\n\\n // MarketStoreUtils errors\\n error MarketNotFound(address key);\\n\\n // MarketUtils errors\\n error EmptyMarket();\\n error DisabledMarket(address market);\\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\\n error UnableToGetOppositeToken(address inputToken, address market);\\n error UnexpectedTokenForVirtualInventory(address token, address market);\\n error EmptyMarketTokenSupply();\\n error InvalidSwapMarket(address market);\\n error UnableToGetCachedTokenPrice(address token, address market);\\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\\n error UnableToGetBorrowingFactorEmptyPoolUsd();\\n error UnableToGetFundingFactorEmptyOpenInterest();\\n error InvalidPositionMarket(address market);\\n error InvalidCollateralTokenForMarket(address market, address token);\\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\\n error UnexpectedPoolValue(int256 poolValue);\\n\\n // MarketPositionImpactUtils errors\\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\\n\\n // Oracle errors\\n error SequencerDown();\\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\\n error EmptyValidatedPrices(); // not used, kept for compatibility\\n error InvalidOracleProvider(address provider);\\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\\n error GmEmptySigner(uint256 signerIndex);\\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\\n error EmptyDataStreamFeedId(address token);\\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\\n error EmptyChainlinkPriceFeedMultiplier(address token);\\n error EmptyDataStreamMultiplier(address token);\\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\\n error InvalidFeedPrice(address token, int256 price);\\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\\n error InvalidGmOraclePrice(address token);\\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\\n error EmptyChainlinkPriceFeed(address token);\\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\\n error MaxRefPriceDeviationExceeded(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n );\\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\\n error NonAtomicOracleProvider(address provider);\\n\\n // OracleModule errors\\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\\n error EndOfOracleSimulation();\\n\\n // OracleUtils errors\\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\\n\\n error EmptyPrimaryPrice(address token);\\n\\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\\n\\n // BaseOrderUtils errors\\n error EmptyOrder();\\n error UnsupportedOrderType(uint256 orderType);\\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\\n error InvalidOrderPrices(\\n uint256 primaryPriceMin,\\n uint256 primaryPriceMax,\\n uint256 triggerPrice,\\n uint256 orderType\\n );\\n error EmptySizeDeltaInTokens();\\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\\n\\n // IncreaseOrderUtils errors\\n error UnexpectedPositionState();\\n\\n // OrderUtils errors\\n error OrderTypeCannotBeCreated(uint256 orderType);\\n error OrderAlreadyFrozen();\\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\\n error InvalidReceiver(address receiver);\\n error UnexpectedValidFromTime(uint256 orderType);\\n\\n // OrderStoreUtils errors\\n error OrderNotFound(bytes32 key);\\n\\n // SwapOrderUtils errors\\n error UnexpectedMarket();\\n\\n // DecreasePositionCollateralUtils errors\\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\\n\\n // DecreasePositionUtils errors\\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\\n error PositionShouldNotBeLiquidated(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n // IncreasePositionUtils errors\\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\\n\\n // PositionStoreUtils errors\\n error PositionNotFound(bytes32 key);\\n\\n // PositionUtils errors\\n error LiquidatablePosition(\\n string reason,\\n int256 remainingCollateralUsd,\\n int256 minCollateralUsd,\\n int256 minCollateralUsdForLeverage\\n );\\n\\n error EmptyPosition();\\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\\n\\n // PositionPricingUtils errors\\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\\n\\n // ShiftStoreUtils errors\\n error ShiftNotFound(bytes32 key);\\n\\n // ShiftUtils errors\\n error EmptyShift();\\n error EmptyShiftAmount();\\n error ShiftFromAndToMarketAreEqual(address market);\\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\\n error BridgeOutNotSupportedDuringShift();\\n\\n // SwapPricingUtils errors\\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\\n\\n // RoleModule errors\\n error Unauthorized(address msgSender, string role);\\n\\n // RoleStore errors\\n error ThereMustBeAtLeastOneRoleAdmin();\\n error ThereMustBeAtLeastOneTimelockMultiSig();\\n\\n // ExchangeRouter errors\\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\\n\\n // SwapUtils errors\\n error InvalidTokenIn(address tokenIn, address market);\\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\\n error DuplicatedMarketInSwapPath(address market);\\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\\n\\n // SubaccountRouter errors\\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\\n\\n // SubaccountUtils errors\\n error SubaccountNotAuthorized(address account, address subaccount);\\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\\n\\n // TokenUtils errors\\n error TokenTransferError(address token, address receiver, uint256 amount);\\n error EmptyHoldingAddress();\\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\\n // some contracts with this error cannot be re-deployed so it has been left as is\\n error EmptyTokenTranferGasLimit(address token);\\n\\n // AccountUtils errors\\n error EmptyAccount();\\n error EmptyReceiver();\\n error DataListLengthExceeded();\\n\\n // ClaimHandler errors\\n error EmptyAmount();\\n error EmptyClaimableAmount(address token);\\n error InvalidToken(address token);\\n error InvalidParams(string reason);\\n error InsufficientFunds(address token);\\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\\n error DuplicateClaimTerms(uint256 existingDistributionId);\\n\\n // Array errors\\n error CompactedArrayOutOfBounds(\\n uint256[] compactedValues,\\n uint256 index,\\n uint256 slotIndex,\\n string label\\n );\\n\\n error ArrayOutOfBoundsUint256(\\n uint256[] values,\\n uint256 index,\\n string label\\n );\\n\\n error ArrayOutOfBoundsBytes(\\n bytes[] values,\\n uint256 index,\\n string label\\n );\\n\\n // WithdrawalHandler errors\\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\\n\\n // WithdrawalStoreUtils errors\\n error WithdrawalNotFound(bytes32 key);\\n\\n // WithdrawalUtils errors\\n error EmptyWithdrawal();\\n error EmptyWithdrawalAmount();\\n error MinLongTokens(uint256 received, uint256 expected);\\n error MinShortTokens(uint256 received, uint256 expected);\\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\\n error InvalidPoolValueForWithdrawal(int256 poolValue);\\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\\n\\n // Uint256Mask errors\\n error MaskIndexOutOfBounds(uint256 index, string label);\\n error DuplicatedIndex(uint256 index, string label);\\n\\n // Cast errors\\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\\n\\n // ConfigSyncer errors\\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\\n error SyncConfigUpdatesDisabledForMarket(address market);\\n error SyncConfigUpdatesDisabledForParameter(string parameter);\\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\\n\\n // Reader errors\\n error EmptyMarketPrice(address market);\\n\\n // Multichain errors\\n error InvalidTransferRequestsLength();\\n error EmptyMultichainTransferInAmount(address account, address token);\\n error EmptyMultichainTransferOutAmount(address account, address token);\\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\\n error InvalidSrcChainId(uint256 srcChainId);\\n error InvalidEid(uint256 eid);\\n error InvalidDestinationChainId(uint256 desChainId);\\n error TokenPermitsNotAllowedForMultichain();\\n error InvalidInitializer();\\n error InvalidMultichainProvider(address provider);\\n error InvalidMultichainEndpoint(address endpoint);\\n error UnableToPayOrderFee();\\n error UnableToPayOrderFeeFromCollateral();\\n error InvalidBridgeOutToken(address token);\\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\\n\\n enum SignatureType {\\n Call,\\n SubaccountApproval\\n }\\n\\n // Gelato relay errors\\n error InvalidSignature(string signatureType);\\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\\n // User sent incorrect fee token or incorrect swap path\\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\\n // Contract received unsupported fee token from Gelato relay\\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\\n error InvalidPermitSpender(address spender, address expectedSpender);\\n error InvalidUserDigest(bytes32 digest);\\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\\n error InvalidSubaccountApprovalSubaccount();\\n error NonEmptyExternalCallsForSubaccountOrder();\\n\\n // EventUtils error\\n error EventItemNotFound(string key);\\n\\n // EdgeOracle verifier errors\\n error InvalidTrustedSignerAddress();\\n error InvalidEdgeSigner();\\n error InvalidEdgeSignature(uint256 recoverError);\\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\\n error InvalidEdgeDataStreamExpo(int256 expo);\\n error RelayEmptyBatch();\\n error RelayCalldataTooLong(uint256 calldataLength);\\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\\n\\n // MultichainReader errors\\n error InsufficientMultichainNativeFee(uint256 msgValue);\\n error EmptyPeer(uint32 eid);\\n\\n // FeeDistributor errors\\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\\n error OutdatedReadResponse(uint256 timestamp);\\n error InvalidDistributionState(uint256 distributionStateUint);\\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\\n error BridgingTransactionFailed(bytes result);\\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\\n error InvalidReferralRewardToken(address token);\\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\\n error ZeroTreasuryAddress();\\n}\\n\",\"keccak256\":\"0xfdaacc5999aa20b6f871f3c628a405e8e6ace02e56dc0b61f4c68744cba9e7d5\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventEmitter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"./EventUtils.sol\\\";\\n\\n// @title EventEmitter\\n// @dev Contract to emit events\\n// This allows main events to be emitted from a single contract\\n// Logic contracts can be updated while re-using the same eventEmitter contract\\n// Peripheral services like monitoring or analytics would be able to continue\\n// to work without an update and without segregating historical data\\ncontract EventEmitter is RoleModule {\\n event EventLog(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog1(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n EventUtils.EventLogData eventData\\n );\\n\\n event EventLog2(\\n address msgSender,\\n string eventName,\\n string indexed eventNameHash,\\n bytes32 indexed topic1,\\n bytes32 indexed topic2,\\n EventUtils.EventLogData eventData\\n );\\n\\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param eventData the event data\\n function emitEventLog(\\n string memory eventName,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog(\\n msg.sender,\\n eventName,\\n eventName,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param eventData the event data\\n function emitEventLog1(\\n string memory eventName,\\n bytes32 topic1,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog1(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n eventData\\n );\\n }\\n\\n // @dev emit a general event log\\n // @param eventName the name of the event\\n // @param topic1 topic1 for indexing\\n // @param topic2 topic2 for indexing\\n // @param eventData the event data\\n function emitEventLog2(\\n string memory eventName,\\n bytes32 topic1,\\n bytes32 topic2,\\n EventUtils.EventLogData memory eventData\\n ) external onlyController {\\n emit EventLog2(\\n msg.sender,\\n eventName,\\n eventName,\\n topic1,\\n topic2,\\n eventData\\n );\\n }\\n\\n\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param data additional data\\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log1(add(data, 32), len, topic1)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param data additional data\\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log2(add(data, 32), len, topic1, topic2)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param data additional data\\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log3(add(data, 32), len, topic1, topic2, topic3)\\n }\\n }\\n\\n // @dev event log for general use\\n // @param topic1 event topic 1\\n // @param topic2 event topic 2\\n // @param topic3 event topic 3\\n // @param topic4 event topic 4\\n // @param data additional data\\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\\n uint256 len = data.length;\\n assembly {\\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8a99c1d3590daa8030345ffb09e3f769a93e0178e4c85986dc0e08cc84e8f82c\",\"license\":\"BUSL-1.1\"},\"contracts/event/EventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\nimport \\\"../utils/StringUtils.sol\\\";\\n\\nlibrary EventUtils {\\n\\n struct EmitPositionDecreaseParams {\\n bytes32 key;\\n address account;\\n address market;\\n address collateralToken;\\n bool isLong;\\n }\\n\\n struct EventLogData {\\n AddressItems addressItems;\\n UintItems uintItems;\\n IntItems intItems;\\n BoolItems boolItems;\\n Bytes32Items bytes32Items;\\n BytesItems bytesItems;\\n StringItems stringItems;\\n }\\n\\n struct AddressItems {\\n AddressKeyValue[] items;\\n AddressArrayKeyValue[] arrayItems;\\n }\\n\\n struct UintItems {\\n UintKeyValue[] items;\\n UintArrayKeyValue[] arrayItems;\\n }\\n\\n struct IntItems {\\n IntKeyValue[] items;\\n IntArrayKeyValue[] arrayItems;\\n }\\n\\n struct BoolItems {\\n BoolKeyValue[] items;\\n BoolArrayKeyValue[] arrayItems;\\n }\\n\\n struct Bytes32Items {\\n Bytes32KeyValue[] items;\\n Bytes32ArrayKeyValue[] arrayItems;\\n }\\n\\n struct BytesItems {\\n BytesKeyValue[] items;\\n BytesArrayKeyValue[] arrayItems;\\n }\\n\\n struct StringItems {\\n StringKeyValue[] items;\\n StringArrayKeyValue[] arrayItems;\\n }\\n\\n struct AddressKeyValue {\\n string key;\\n address value;\\n }\\n\\n struct AddressArrayKeyValue {\\n string key;\\n address[] value;\\n }\\n\\n struct UintKeyValue {\\n string key;\\n uint256 value;\\n }\\n\\n struct UintArrayKeyValue {\\n string key;\\n uint256[] value;\\n }\\n\\n struct IntKeyValue {\\n string key;\\n int256 value;\\n }\\n\\n struct IntArrayKeyValue {\\n string key;\\n int256[] value;\\n }\\n\\n struct BoolKeyValue {\\n string key;\\n bool value;\\n }\\n\\n struct BoolArrayKeyValue {\\n string key;\\n bool[] value;\\n }\\n\\n struct Bytes32KeyValue {\\n string key;\\n bytes32 value;\\n }\\n\\n struct Bytes32ArrayKeyValue {\\n string key;\\n bytes32[] value;\\n }\\n\\n struct BytesKeyValue {\\n string key;\\n bytes value;\\n }\\n\\n struct BytesArrayKeyValue {\\n string key;\\n bytes[] value;\\n }\\n\\n struct StringKeyValue {\\n string key;\\n string value;\\n }\\n\\n struct StringArrayKeyValue {\\n string key;\\n string[] value;\\n }\\n\\n function initItems(AddressItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.AddressKeyValue[](size);\\n }\\n\\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\\n (bool found, address value) = getWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\\n for (uint i = 0; i < addresses.items.length; i++) {\\n if (compareStrings(addresses.items[i].key, key)) {\\n return (true, addresses.items[i].value);\\n }\\n }\\n return (false, address(0));\\n }\\n\\n function getArray(AddressItems memory addresses, string memory key) external pure\\n returns(address[] memory) {\\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\\n returns(bool, address[] memory) {\\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\\n if (compareStrings(addresses.arrayItems[i].key, key)) {\\n return (true, addresses.arrayItems[i].value);\\n }\\n }\\n address[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(UintItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.UintKeyValue[](size);\\n }\\n\\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\\n (bool found, uint256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(UintItems memory items, string memory key) external pure\\n returns(uint256[] memory) {\\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\\n returns(bool, uint256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n uint256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(IntItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.IntKeyValue[](size);\\n }\\n\\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(IntItems memory items, string memory key) external pure returns(int256) {\\n (bool found, int256 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(IntItems memory items, string memory key) external pure\\n returns(int256[] memory) {\\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\\n returns(bool, int256[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n int256[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BoolItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BoolKeyValue[](size);\\n }\\n\\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\\n (bool found, bool value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, false);\\n }\\n\\n function getArray(BoolItems memory items, string memory key) external pure\\n returns(bool[] memory) {\\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\\n returns(bool, bool[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bool[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.items = new EventUtils.Bytes32KeyValue[](size);\\n }\\n\\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\\n (bool found, bytes32 value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, 0);\\n }\\n\\n function getArray(Bytes32Items memory items, string memory key) external pure\\n returns(bytes32[] memory) {\\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\\n returns(bool, bytes32[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes32[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(BytesItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.BytesKeyValue[](size);\\n }\\n\\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\\n (bool found, bytes memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(BytesItems memory items, string memory key) external pure\\n returns(bytes[] memory) {\\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\\n returns(bool, bytes[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n bytes[] memory empty;\\n return (false, empty);\\n }\\n\\n function initItems(StringItems memory items, uint256 size) internal pure {\\n items.items = new EventUtils.StringKeyValue[](size);\\n }\\n\\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\\n items.items[index].key = key;\\n items.items[index].value = value;\\n }\\n\\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\\n items.arrayItems[index].key = key;\\n items.arrayItems[index].value = value;\\n }\\n\\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\\n (bool found, string memory value) = getWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\\n for (uint i = 0; i < items.items.length; i++) {\\n if (compareStrings(items.items[i].key, key)) {\\n return (true, items.items[i].value);\\n }\\n }\\n return (false, \\\"\\\");\\n }\\n\\n function getArray(StringItems memory items, string memory key) external pure\\n returns(string[] memory) {\\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\\n if (!found) {\\n revert Errors.EventItemNotFound(key);\\n }\\n return value;\\n }\\n\\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\\n returns(bool, string[] memory) {\\n for (uint i = 0; i < items.arrayItems.length; i++) {\\n if (compareStrings(items.arrayItems[i].key, key)) {\\n return (true, items.arrayItems[i].value);\\n }\\n }\\n string[] memory empty;\\n return (false, empty);\\n }\\n\\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\\n return StringUtils.compareStrings(a, b);\\n }\\n}\\n\",\"keccak256\":\"0x4fc9dd0bed17a086fc9f5c5e785be7e6ab2ba21ad19db5b1c4337bf9c322fd35\",\"license\":\"BUSL-1.1\"},\"contracts/feature/FeatureUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\n\\n// @title FeatureUtils\\n// @dev Library to validate if a feature is enabled or disabled\\n// disabling a feature should only be used if it is absolutely necessary\\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\\n// could be disabled while liquidations may remain enabled\\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\\n// when block production resumes\\n// the effects of disabling features should be carefully considered\\nlibrary FeatureUtils {\\n // @dev get whether a feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n // @return whether the feature is disabled\\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\\n return dataStore.getBool(key);\\n }\\n\\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\\n // @param dataStore DataStore\\n // @param key the feature key\\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\\n if (isFeatureDisabled(dataStore, key)) {\\n revert Errors.DisabledFeature(key);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x148b6e67d2d84b46006ac0b8871902bfe3d1398aae986568c989c4f3edf8d41a\",\"license\":\"BUSL-1.1\"},\"contracts/market/Market.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Market\\n// @dev Struct for markets\\n//\\n// Markets support both spot and perp trading, they are created by specifying a\\n// long collateral token, short collateral token and index token.\\n//\\n// Examples:\\n//\\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\\n//\\n// Liquidity providers can deposit either the long or short collateral token or\\n// both to mint liquidity tokens.\\n//\\n// The long collateral token is used to back long positions, while the short\\n// collateral token is used to back short positions.\\n//\\n// Liquidity providers take on the profits and losses of traders for the market\\n// that they provide liquidity for.\\n//\\n// Having separate markets allows for risk isolation, liquidity providers are\\n// only exposed to the markets that they deposit into, this potentially allow\\n// for permissionless listings.\\n//\\n// Traders can use either the long or short token as collateral for the market.\\nlibrary Market {\\n // @param marketToken address of the market token for the market\\n // @param indexToken address of the index token for the market\\n // @param longToken address of the long token for the market\\n // @param shortToken address of the short token for the market\\n // @param data for any additional data\\n struct Props {\\n address marketToken;\\n address indexToken;\\n address longToken;\\n address shortToken;\\n }\\n}\\n\",\"keccak256\":\"0xbc17a22c0a7f183bfd6d3fe74b8de404733dee1f035923acca1d69012b7b7e28\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\n\\nlibrary MarketEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n // this event is emitted before a deposit or withdrawal\\n // it provides information of the pool state so that the amount\\n // of market tokens minted or amount withdrawn from the pool can be checked\\n function emitMarketPoolValueInfo(\\n EventEmitter eventEmitter,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueInfo\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n // this event is emitted after a deposit or withdrawal\\n // it provides information of the updated pool state\\n // note that the pool state can change even without a deposit / withdrawal\\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\\n // will change as index prices change\\n function emitMarketPoolValueUpdated(\\n EventEmitter eventEmitter,\\n bytes32 actionType,\\n bytes32 tradeKey,\\n address market,\\n MarketPoolValueInfo.Props memory props,\\n uint256 marketTokensSupply\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.bytes32Items.initItems(2);\\n eventData.bytes32Items.setItem(0, \\\"actionType\\\", actionType);\\n eventData.bytes32Items.setItem(1, \\\"tradeKey\\\", tradeKey);\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(4);\\n eventData.intItems.setItem(0, \\\"poolValue\\\", props.poolValue);\\n eventData.intItems.setItem(1, \\\"longPnl\\\", props.longPnl);\\n eventData.intItems.setItem(2, \\\"shortPnl\\\", props.shortPnl);\\n eventData.intItems.setItem(3, \\\"netPnl\\\", props.netPnl);\\n\\n eventData.uintItems.initItems(8);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", props.longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", props.shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"longTokenUsd\\\", props.longTokenUsd);\\n eventData.uintItems.setItem(3, \\\"shortTokenUsd\\\", props.shortTokenUsd);\\n eventData.uintItems.setItem(4, \\\"totalBorrowingFees\\\", props.totalBorrowingFees);\\n eventData.uintItems.setItem(5, \\\"borrowingFeePoolFactor\\\", props.borrowingFeePoolFactor);\\n eventData.uintItems.setItem(6, \\\"impactPoolAmount\\\", props.impactPoolAmount);\\n eventData.uintItems.setItem(7, \\\"marketTokensSupply\\\", marketTokensSupply);\\n\\n eventEmitter.emitEventLog1(\\n \\\"MarketPoolValueUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitSwapImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SwapImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolDistributed(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 distributionAmount,\\n uint256 nextPositionImpactPoolAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"distributionAmount\\\", distributionAmount);\\n eventData.uintItems.setItem(1, \\\"nextPositionImpactPoolAmount\\\", nextPositionImpactPoolAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolDistributed\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitTotalPendingImpactAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"TotalPendingImpactAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentPositionImpactPoolAmountUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentPositionImpactPoolAmountUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitOpenInterestUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitVirtualSwapInventoryUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLongToken,\\n bytes32 virtualMarketId,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLongToken\\\", isLongToken);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualMarketId\\\", virtualMarketId);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualSwapInventoryUpdated\\\",\\n Cast.toBytes32(market),\\n virtualMarketId,\\n eventData\\n );\\n }\\n\\n function emitVirtualPositionInventoryUpdated(\\n EventEmitter eventEmitter,\\n address token,\\n bytes32 virtualTokenId,\\n int256 delta,\\n int256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n\\n eventData.bytes32Items.initItems(1);\\n eventData.bytes32Items.setItem(0, \\\"virtualTokenId\\\", virtualTokenId);\\n\\n eventData.intItems.initItems(2);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n eventData.intItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"VirtualPositionInventoryUpdated\\\",\\n Cast.toBytes32(token),\\n virtualTokenId,\\n eventData\\n );\\n }\\n\\n function emitOpenInterestInTokensUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OpenInterestInTokensUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitCollateralSumUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.intItems.initItems(1);\\n eventData.intItems.setItem(0, \\\"delta\\\", delta);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralSumUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowing(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 borrowingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"borrowingFactorPerSecond\\\", borrowingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Borrowing\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitBorrowingFactorUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CumulativeBorrowingFactorUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFunding(\\n EventEmitter eventEmitter,\\n address market,\\n uint256 fundingFactorPerSecond\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"fundingFactorPerSecond\\\", fundingFactorPerSecond);\\n\\n eventEmitter.emitEventLog1(\\n \\\"Funding\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitFundingFeeAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeeAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingAmountPerSizeUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta,\\n uint256 value\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"collateralToken\\\", collateralToken);\\n\\n eventData.boolItems.initItems(1);\\n eventData.boolItems.setItem(0, \\\"isLong\\\", isLong);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"value\\\", value);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingAmountPerSizeUpdated\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitFundingFeesClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"FundingFeesClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableFundingUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableFundingUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitClaimableCollateralUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(4);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(2, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(3, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"ClaimableCollateralUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitCollateralClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"account\\\", account);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"timeKey\\\", timeKey);\\n eventData.uintItems.setItem(1, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"CollateralClaimed\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitUiFeeFactorUpdated(\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) external {\\n\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"uiFeeFactor\\\", uiFeeFactor);\\n\\n eventEmitter.emitEventLog1(\\n \\\"UiFeeFactorUpdated\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n function emitPositionImpactPoolWithdrawal(\\n EventEmitter eventEmitter,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(1);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"PositionImpactPoolWithdrawal\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n\\n function emitLentImpactAmountReduction(\\n EventEmitter eventEmitter,\\n address market,\\n address fundingAccount,\\n uint256 longTokenAmount,\\n uint256 shortTokenAmount,\\n uint256 reductionAmount\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"fundingAccount\\\", fundingAccount);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"longTokenAmount\\\", longTokenAmount);\\n eventData.uintItems.setItem(1, \\\"shortTokenAmount\\\", shortTokenAmount);\\n eventData.uintItems.setItem(2, \\\"reductionAmount\\\", reductionAmount);\\n\\n eventEmitter.emitEventLog1(\\n \\\"LentImpactAmountReduction\\\",\\n Cast.toBytes32(market),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe422f93a48ce7c510f1bcc34ddff63ede427d72be33da136d904f186d1d93130\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketPoolValueInfo.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title MarketPoolInfo\\nlibrary MarketPoolValueInfo {\\n // @dev struct to avoid stack too deep errors for the getPoolValue call\\n // @param poolValue the value of the pool in USD\\n // @param longPnl the pending pnl of long positions\\n // @param shortPnl the pending pnl of short positions\\n // @param netPnl the net pnl of long and short positions\\n // @param longTokenAmount the amount of long token in the pool\\n // @param shortTokenAmount the amount of short token in the pool\\n // @param longTokenUsd the USD value of the long tokens in the pool\\n // @param shortTokenUsd the USD value of the short tokens in the pool\\n // @param totalBorrowingFees the total pending borrowing fees for the market\\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\\n // @param impactPoolAmount the amount of tokens in the impact pool\\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\\n struct Props {\\n int256 poolValue;\\n int256 longPnl;\\n int256 shortPnl;\\n int256 netPnl;\\n\\n uint256 longTokenAmount;\\n uint256 shortTokenAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n\\n uint256 totalBorrowingFees;\\n uint256 borrowingFeePoolFactor;\\n\\n uint256 impactPoolAmount;\\n uint256 lentImpactPoolAmount;\\n }\\n}\\n\",\"keccak256\":\"0x7c67aba3cd6e9aa0fd74a98901698e3c106204ec19ecf003d99ae74808ac721c\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketStoreUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\n\\n/**\\n * @title MarketStoreUtils\\n * @dev Library for market storage functions\\n */\\nlibrary MarketStoreUtils {\\n using Market for Market.Props;\\n\\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\\\"MARKET_SALT\\\"));\\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\\\"MARKET_KEY\\\"));\\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\\\"MARKET_TOKEN\\\"));\\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\\\"INDEX_TOKEN\\\"));\\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\\\"LONG_TOKEN\\\"));\\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\\\"SHORT_TOKEN\\\"));\\n\\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\\n Market.Props memory market;\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n return market;\\n }\\n\\n market.marketToken = dataStore.getAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n market.indexToken = dataStore.getAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n market.longToken = dataStore.getAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n market.shortToken = dataStore.getAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n return market;\\n }\\n\\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\\n address key = dataStore.getAddress(getMarketSaltHash(salt));\\n return get(dataStore, key);\\n }\\n\\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\\n dataStore.addAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n // the salt is based on the market props while the key gives the market's address\\n // use the salt to store a reference to the key to allow the key to be retrieved\\n // using just the salt value\\n dataStore.setAddress(\\n getMarketSaltHash(salt),\\n key\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN)),\\n market.marketToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN)),\\n market.indexToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, LONG_TOKEN)),\\n market.longToken\\n );\\n\\n dataStore.setAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN)),\\n market.shortToken\\n );\\n }\\n\\n function remove(DataStore dataStore, address key, bytes32 salt) external {\\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\\n revert Errors.MarketNotFound(key);\\n }\\n\\n dataStore.removeAddress(\\n Keys.MARKET_LIST,\\n key\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, MARKET_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, INDEX_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, LONG_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n keccak256(abi.encode(key, SHORT_TOKEN))\\n );\\n\\n dataStore.removeAddress(\\n getMarketSaltHash(salt)\\n );\\n }\\n\\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\\n return keccak256(abi.encode(MARKET_SALT, salt));\\n }\\n\\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\\n return dataStore.getAddressCount(Keys.MARKET_LIST);\\n }\\n\\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\\n }\\n}\\n\",\"keccak256\":\"0x0926d1fa022985793085dda876fe3d6fc0c65ecbfea37ac3c1a75ded64c4aeca\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketToken.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\n\\n// @title MarketToken\\n// @dev The market token for a market, stores funds for the market and keeps track\\n// of the liquidity owners\\ncontract MarketToken is ERC20, Bank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\\\"GMX Market\\\", \\\"GM\\\") Bank(_roleStore, _dataStore) {\\n }\\n\\n // @dev mint market tokens to an account\\n // @param account the account to mint to\\n // @param amount the amount of tokens to mint\\n function mint(address account, uint256 amount) external onlyController {\\n _mint(account, amount);\\n }\\n\\n // @dev burn market tokens from an account\\n // @param account the account to burn tokens for\\n // @param amount the amount of tokens to burn\\n function burn(address account, uint256 amount) external onlyController {\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x8a6b725d7baf6258117529a8d7627195a088b1b45d7490ec9866974c10429d6f\",\"license\":\"BUSL-1.1\"},\"contracts/market/MarketUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\n\\nimport \\\"./Market.sol\\\";\\nimport \\\"./MarketPoolValueInfo.sol\\\";\\nimport \\\"./MarketToken.sol\\\";\\nimport \\\"./MarketEventUtils.sol\\\";\\nimport \\\"./MarketStoreUtils.sol\\\";\\n\\nimport \\\"../position/Position.sol\\\";\\nimport \\\"../order/Order.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"../feature/FeatureUtils.sol\\\";\\n\\n// @title MarketUtils\\n// @dev Library for market functions\\nlibrary MarketUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Market for Market.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n enum FundingRateChangeType {\\n NoChange,\\n Increase,\\n Decrease\\n }\\n\\n // @dev struct to store the prices of tokens of a market\\n // @param indexTokenPrice price of the market's index token\\n // @param longTokenPrice price of the market's long token\\n // @param shortTokenPrice price of the market's short token\\n struct MarketPrices {\\n Price.Props indexTokenPrice;\\n Price.Props longTokenPrice;\\n Price.Props shortTokenPrice;\\n }\\n\\n struct CollateralType {\\n uint256 longToken;\\n uint256 shortToken;\\n }\\n\\n struct PositionType {\\n CollateralType long;\\n CollateralType short;\\n }\\n\\n // @dev struct for the result of the getNextFundingAmountPerSize call\\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\\n // see getNextFundingFactorPerSecond for more info\\n struct GetNextFundingAmountPerSizeResult {\\n bool longsPayShorts;\\n uint256 fundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecond;\\n\\n PositionType fundingFeeAmountPerSizeDelta;\\n PositionType claimableFundingAmountPerSizeDelta;\\n }\\n\\n struct GetNextFundingAmountPerSizeCache {\\n PositionType openInterest;\\n\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n uint256 durationInSeconds;\\n\\n uint256 sizeOfPayingSide;\\n uint256 fundingUsd;\\n\\n uint256 fundingUsdForLongCollateral;\\n uint256 fundingUsdForShortCollateral;\\n }\\n\\n struct GetNextFundingFactorPerSecondCache {\\n uint256 diffUsd;\\n uint256 totalOpenInterest;\\n\\n uint256 fundingFactor;\\n uint256 fundingExponentFactor;\\n\\n uint256 diffUsdAfterExponent;\\n uint256 diffUsdToOpenInterestFactor;\\n\\n int256 savedFundingFactorPerSecond;\\n uint256 savedFundingFactorPerSecondMagnitude;\\n\\n int256 nextSavedFundingFactorPerSecond;\\n int256 nextSavedFundingFactorPerSecondWithMinBound;\\n }\\n\\n struct FundingConfigCache {\\n uint256 thresholdForStableFunding;\\n uint256 thresholdForDecreaseFunding;\\n\\n uint256 fundingIncreaseFactorPerSecond;\\n uint256 fundingDecreaseFactorPerSecond;\\n\\n uint256 minFundingFactorPerSecond;\\n uint256 maxFundingFactorPerSecond;\\n }\\n\\n struct GetExpectedMinTokenBalanceCache {\\n uint256 poolAmount;\\n uint256 swapImpactPoolAmount;\\n uint256 claimableCollateralAmount;\\n uint256 claimableFeeAmount;\\n uint256 claimableUiFeeAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct ApplyDeltaToPositionImpactPoolCache {\\n bytes32 positionImpactPoolAmountKey;\\n bytes32 lentPositionImpactPoolAmountKey;\\n uint256 deltaMagnitude;\\n uint256 poolAmount;\\n uint256 excessAmount;\\n uint256 nextValue;\\n }\\n\\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\\n uint256 impactPoolAmount;\\n uint256 impactPoolUsd;\\n uint256 lentAmount;\\n uint256 longTokenUsd;\\n uint256 shortTokenUsd;\\n uint256 maxLendableUsd;\\n uint256 maxPriceImpactUsd;\\n uint256 usdRequiredToBeLent;\\n }\\n\\n // @dev get the market token's price\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longTokenPrice the price of the long token\\n // @param shortTokenPrice the price of the short token\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the market token price\\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\\n function getMarketTokenPrice(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\\n dataStore,\\n market,\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice,\\n pnlFactorType,\\n maximize\\n );\\n\\n // if the supply is zero then treat the market token price as 1 USD\\n if (supply == 0) {\\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\\n }\\n\\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\\n\\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\\n return (marketTokenPrice, poolValueInfo);\\n }\\n\\n // @dev get the total supply of the marketToken\\n // @param marketToken the marketToken\\n // @return the total supply of the marketToken\\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\\n return marketToken.totalSupply();\\n }\\n\\n // @dev get the opposite token of the market\\n // if the inputToken is the longToken return the shortToken and vice versa\\n // @param inputToken the input token\\n // @param market the market values\\n // @return the opposite token\\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\\n if (inputToken == market.longToken) {\\n return market.shortToken;\\n }\\n\\n if (inputToken == market.shortToken) {\\n return market.longToken;\\n }\\n\\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n }\\n\\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (market.longToken == market.shortToken) {\\n revert Errors.InvalidSwapMarket(market.marketToken);\\n }\\n }\\n\\n // @dev get the token price from the stored MarketPrices\\n // @param token the token to get the price for\\n // @param the market values\\n // @param the market token prices\\n // @return the token price from the stored MarketPrices\\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\\n if (token == market.longToken) {\\n return prices.longTokenPrice;\\n }\\n if (token == market.shortToken) {\\n return prices.shortTokenPrice;\\n }\\n if (token == market.indexToken) {\\n return prices.indexTokenPrice;\\n }\\n\\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\\n }\\n\\n // @dev return the primary prices for the market tokens\\n // @param oracle Oracle\\n // @param market the market values\\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\\n return MarketPrices(\\n oracle.getPrimaryPrice(market.indexToken),\\n oracle.getPrimaryPrice(market.longToken),\\n oracle.getPrimaryPrice(market.shortToken)\\n );\\n }\\n\\n // @dev get the usd value of either the long or short tokens in the pool\\n // without accounting for the pnl of open positions\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param whether to return the value for the long or short token\\n // @return the usd value of either the long or short tokens in the pool\\n function getPoolUsdWithoutPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (uint256) {\\n address token = isLong ? market.longToken : market.shortToken;\\n // note that if it is a single token market, the poolAmount returned will be\\n // the amount of tokens in the pool divided by 2\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 tokenPrice;\\n\\n if (maximize) {\\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\\n } else {\\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n }\\n\\n return poolAmount * tokenPrice;\\n }\\n\\n // @dev get the USD value of a pool\\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\\n // net price impact should be zero\\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\\n // if these amounts are large they may be a significant contributor to the GM token price\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param longTokenPrice price of the long token\\n // @param shortTokenPrice price of the short token\\n // @param indexTokenPrice price of the index token\\n // @param maximize whether to maximize or minimize the pool value\\n // @return the value information of a pool\\n function getPoolValueInfo(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n Price.Props memory longTokenPrice,\\n Price.Props memory shortTokenPrice,\\n bytes32 pnlFactorType,\\n bool maximize\\n ) public view returns (MarketPoolValueInfo.Props memory) {\\n MarketPoolValueInfo.Props memory result;\\n\\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\\n\\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\\n\\n MarketPrices memory prices = MarketPrices(\\n indexTokenPrice,\\n longTokenPrice,\\n shortTokenPrice\\n );\\n\\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n true\\n );\\n\\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\\n dataStore,\\n market,\\n prices,\\n false\\n );\\n\\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\\n\\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\\n // and a smaller pnl leads to a larger pool value\\n //\\n // while positions will always be closed at the less favourable price\\n // using the inverse of maximize for the getPnl calls would help prevent\\n // gaming of market token values by increasing the spread\\n //\\n // liquidations could be triggered by manipulating a large spread but\\n // that should be more difficult to execute\\n\\n result.longPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n true, // isLong\\n !maximize // maximize\\n );\\n\\n result.longPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n true,\\n result.longPnl,\\n result.longTokenUsd,\\n pnlFactorType\\n );\\n\\n result.shortPnl = getPnl(\\n dataStore,\\n market,\\n indexTokenPrice,\\n false, // isLong\\n !maximize // maximize\\n );\\n\\n result.shortPnl = getCappedPnl(\\n dataStore,\\n market.marketToken,\\n false,\\n result.shortPnl,\\n result.shortTokenUsd,\\n pnlFactorType\\n );\\n\\n result.netPnl = result.longPnl + result.shortPnl;\\n result.poolValue = result.poolValue - result.netPnl;\\n\\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\\n\\n result.poolValue -= impactPoolUsd.toInt256();\\n\\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\\n\\n result.poolValue += lentImpactPoolUsd.toInt256();\\n\\n return result;\\n }\\n\\n // @dev get the net pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the net pending pnl for a market\\n function getNetPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\\n\\n return longPnl + shortPnl;\\n }\\n\\n // @dev get the capped pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check for the long or short side\\n // @param pnl the uncapped pnl of the market\\n // @param poolUsd the USD value of the pool\\n // @param pnlFactorType the pnl factor type to use\\n function getCappedPnl(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n int256 pnl,\\n uint256 poolUsd,\\n bytes32 pnlFactorType\\n ) internal view returns (int256) {\\n if (pnl < 0) { return pnl; }\\n\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\\n\\n return pnl > maxPnl ? maxPnl : pnl;\\n }\\n\\n // @dev get the pending pnl for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check for the long or short side\\n // @param maximize whether to maximize or minimize the pnl\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n uint256 indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\\n\\n return getPnl(\\n dataStore,\\n market,\\n _indexTokenPrice,\\n isLong,\\n maximize\\n );\\n }\\n\\n // @dev get the pending pnl for a market for either longs or shorts\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to get the pnl for longs or shorts\\n // @param maximize whether to maximize or minimize the net pnl\\n // @return the pending pnl for a market for either longs or shorts\\n function getPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n if (openInterest == 0 || openInterestInTokens == 0) {\\n return 0;\\n }\\n\\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\\n\\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\\n\\n return pnl;\\n }\\n\\n // @dev get the amount of tokens in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the amount of tokens in the pool\\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\\n // if the longToken and shortToken are the same, return half of the token amount, so that\\n // calculations of pool value, etc would be correct\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\\n }\\n\\n // @dev get the max amount of tokens allowed to be in the pool\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the max amount of tokens that are allowed in the pool\\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\\n }\\n\\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\\n }\\n\\n function getUsageFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd\\n ) internal view returns (uint256) {\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\\n\\n return reserveUsageFactor;\\n }\\n\\n // @dev get the max open interest allowed for the market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether this is for the long or short side\\n // @return the max open interest allowed for the market\\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\\n }\\n\\n // @dev increment the claimable collateral amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the claimable collateral for\\n // @param token the claimable token\\n // @param account the account to increment the claimable collateral for\\n // @param delta the amount to increment\\n function incrementClaimableCollateralAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n uint256 timeKey = Chain.currentTimestamp() / divisor;\\n\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableCollateralUpdated(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev increment the claimable funding amount\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param token the claimable token\\n // @param account the account to increment for\\n // @param delta the amount to increment\\n function incrementClaimableFundingAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n uint256 delta\\n ) internal {\\n uint256 nextValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token, account),\\n delta\\n );\\n\\n uint256 nextPoolValue = dataStore.incrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingUpdated(\\n eventEmitter,\\n market,\\n token,\\n account,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev claim funding fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimFundingFees(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\\n\\n uint256 claimableAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableFundingAmountKey(market, token),\\n claimableAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n claimableAmount\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitFundingFeesClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n claimableAmount,\\n nextPoolValue\\n );\\n\\n return claimableAmount;\\n }\\n\\n function batchClaimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n uint256[] memory timeKeys,\\n address receiver,\\n address account\\n ) internal returns (uint256[] memory) {\\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = MarketUtils.claimCollateral(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n timeKeys[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n // @dev claim collateral\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to claim for\\n // @param token the token to claim\\n // @param timeKey the time key\\n // @param account the account to claim for\\n // @param receiver the receiver to send the amount to\\n function claimCollateral(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account,\\n address receiver\\n ) internal returns (uint256) {\\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\\n\\n if (claimableFactor > Precision.FLOAT_PRECISION) {\\n revert Errors.InvalidClaimableFactor(claimableFactor);\\n }\\n\\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\\n\\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\\n if (adjustedClaimableAmount <= claimedAmount) {\\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\\n }\\n\\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\\n\\n dataStore.setUint(\\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\\n adjustedClaimableAmount\\n );\\n\\n uint256 nextPoolValue = dataStore.decrementUint(\\n Keys.claimableCollateralAmountKey(market, token),\\n amountToBeClaimed\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n amountToBeClaimed\\n );\\n\\n validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitCollateralClaimed(\\n eventEmitter,\\n market,\\n token,\\n timeKey,\\n account,\\n receiver,\\n amountToBeClaimed,\\n nextPoolValue\\n );\\n\\n return amountToBeClaimed;\\n }\\n\\n function _getClaimableFactor(\\n DataStore dataStore,\\n address market,\\n address token,\\n uint256 timeKey,\\n address account\\n ) internal view returns (uint256) {\\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\\n ? claimableFactorForTime\\n : claimableFactorForAccount;\\n\\n // if the divisor is changed the timeDiff calculation would no longer be accurate\\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\\n\\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\\n\\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\\n claimableFactor = Precision.FLOAT_PRECISION;\\n }\\n\\n if (claimableFactor > claimableReductionFactor) {\\n claimableFactor -= claimableReductionFactor;\\n } else {\\n claimableFactor = 0;\\n }\\n\\n return claimableFactor;\\n }\\n\\n // @dev apply a delta to the pool amount\\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\\n // is called when receiving fees\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToPoolAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.poolAmountKey(market.marketToken, token),\\n delta,\\n \\\"Invalid state, negative poolAmount\\\"\\n );\\n\\n applyDeltaToVirtualInventoryForSwaps(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n delta\\n );\\n\\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\\n }\\n\\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\\n\\n // if the positive impact factor is more than the negative impact factor, positions could be opened\\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\\n if (positiveImpactFactor > negativeImpactFactor) {\\n positiveImpactFactor = negativeImpactFactor;\\n }\\n\\n return (positiveImpactFactor, negativeImpactFactor);\\n }\\n\\n // @dev cap the input priceImpactUsd by the available amount in the\\n // position impact pool\\n // Note that since the price impact can be capped, a malicious\\n // CONFIG_KEEPER can set price impact values to be very large\\n // then make trades to incur a large amount of negative price impact\\n // in account A, and a large amount of positive price impact in\\n // account B\\n // since the price impact in account A is claimable, and the positive\\n // price impact in account B is first paid for by the pool, this method\\n // can be used to reduce the funds in the GM pool\\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\\n // 24 hours or more to allow for activity of this form to be blocked\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param indexTokenPrice the price of the token\\n // @param priceImpactUsd the calculated USD price impact\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByPositionImpactPool(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n int256 priceImpactUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd <= 0) {\\n return priceImpactUsd;\\n }\\n\\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\\n\\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\\n\\n // the totalPendingImpactAmount is not factored into the capping here\\n // we assume that the ratio of negative impact to positive impact and\\n // ratio of negative impact cap to positive impact cap is such that the\\n // total negative impact will be more than the positive impact for\\n // majority of the time\\n // additionally, since there is capping of price impact, the\\n // totalPendingImpactAmount would not give an accurate representation\\n // of the actual price impact that would be realised\\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\\n\\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\\n // need to be capped here\\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\\n }\\n\\n // if usdRequiredToBeLent > 0, check how much is lendable\\n if (cache.usdRequiredToBeLent > 0) {\\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\\n // the lent amount from being too large relative to the amounts in the pool\\n // trader pnl, borrowing fees, etc is not factored into this calculation\\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\\n\\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\\n dataStore,\\n market.marketToken,\\n cache.longTokenUsd + cache.shortTokenUsd,\\n prices.indexTokenPrice.max,\\n cache.lentAmount\\n );\\n\\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\\n }\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getMaxLendableUsdAvailable(\\n DataStore dataStore,\\n address market,\\n uint256 poolUsd,\\n uint256 indexTokenPrice,\\n uint256 lentAmount\\n ) internal view returns (uint256) {\\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\\n\\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\\n if (maxLendableUsd > maxLendableUsdConfig) {\\n maxLendableUsd = maxLendableUsdConfig;\\n }\\n\\n uint256 lentUsd = lentAmount * indexTokenPrice;\\n\\n if (lentUsd > maxLendableUsd) {\\n return 0;\\n }\\n\\n return maxLendableUsd - lentUsd;\\n }\\n\\n // @dev cap the input priceImpactUsd by the max positive position impact factor\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param priceImpactUsd the calculated USD price impact\\n // @param sizeDeltaUsd the size by which the position is increased/decreased\\n // @return the capped priceImpactUsd\\n function capPositiveImpactUsdByMaxPositionImpact(\\n DataStore dataStore,\\n address market,\\n int256 priceImpactUsd,\\n uint256 sizeDeltaUsd\\n ) internal view returns (int256) {\\n if (priceImpactUsd < 0) {\\n return priceImpactUsd;\\n }\\n\\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\\n\\n // capped by the positive price impact\\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\\n }\\n\\n return priceImpactUsd;\\n }\\n\\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\\n }\\n\\n // @dev get the position impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the position impact pool amount\\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\\n }\\n\\n // @dev get the swap impact pool amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n // @return the swap impact pool amount\\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\\n }\\n\\n // @dev apply a delta to the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param delta the delta amount\\n function applyDeltaToSwapImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.swapImpactPoolAmountKey(market, token),\\n delta\\n );\\n\\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n function applyDeltaToTotalPendingImpactAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal returns (int256) {\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.totalPendingImpactAmountKey(market),\\n delta\\n );\\n\\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\\n eventEmitter,\\n market,\\n delta,\\n nextValue\\n );\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the position impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param delta the delta amount\\n function applyDeltaToPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n int256 delta\\n ) internal {\\n ApplyDeltaToPositionImpactPoolCache memory cache;\\n cache.deltaMagnitude = delta.abs();\\n\\n if (delta < 0) {\\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n } else {\\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\\n\\n if (cache.deltaMagnitude > cache.poolAmount) {\\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\\n\\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\\n\\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\\n } else {\\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\\n }\\n }\\n }\\n\\n // @dev apply a delta to the open interest\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterest(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n if (market.indexToken == address(0)) {\\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\\n }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest\\\"\\n );\\n\\n // if the open interest for longs is increased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\\n // so the virtual inventory should be increased\\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\\n // so the virtual inventory should be decreased\\n applyDeltaToVirtualInventoryForPositions(\\n dataStore,\\n eventEmitter,\\n market.indexToken,\\n isLong ? -delta : delta\\n );\\n\\n if (delta > 0) {\\n validateOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n }\\n\\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the open interest in tokens\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToOpenInterestInTokens(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative open interest in tokens\\\"\\n );\\n\\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev apply a delta to the collateral sum\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param collateralToken the collateralToken to apply to\\n // @param isLong whether to apply to the long or short side\\n // @param delta the delta amount\\n function applyDeltaToCollateralSum(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n int256 delta\\n ) internal returns (uint256) {\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.collateralSumKey(market, collateralToken, isLong),\\n delta,\\n \\\"Invalid state: negative collateralSum\\\"\\n );\\n\\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\\n\\n return nextValue;\\n }\\n\\n // @dev update the funding state\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param prices the prices of the market tokens\\n function updateFundingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) external {\\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.fundingFeeAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToFundingFeeAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.fundingFeeAmountPerSizeDelta.short.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.longToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.longToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n true,\\n result.claimableFundingAmountPerSizeDelta.long.shortToken\\n );\\n\\n applyDeltaToClaimableFundingAmountPerSize(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n market.shortToken,\\n false,\\n result.claimableFundingAmountPerSizeDelta.short.shortToken\\n );\\n\\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\\n\\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitFunding(\\n eventEmitter,\\n market.marketToken,\\n result.fundingFactorPerSecond\\n );\\n }\\n\\n // @dev get the next funding amount per size values\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n function getNextFundingAmountPerSize(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices\\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\\n GetNextFundingAmountPerSizeResult memory result;\\n GetNextFundingAmountPerSizeCache memory cache;\\n\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n\\n // get the open interest values by long / short and by collateral used\\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\\n\\n // sum the open interest values to get the total long and short open interest values\\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\\n\\n // if either long or short open interest is zero, then funding should not be updated\\n // as there would not be any user to pay the funding to\\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\\n return result;\\n }\\n\\n // if the blockchain is not progressing / a market is disabled, funding fees\\n // will continue to accumulate\\n // this should be a rare occurrence so funding fees are not adjusted for this case\\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\\n\\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\\n dataStore,\\n market.marketToken,\\n cache.longOpenInterest,\\n cache.shortOpenInterest,\\n cache.durationInSeconds\\n );\\n\\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\\n\\n // for single token markets, if there is $200,000 long open interest\\n // and $100,000 short open interest and if the fundingUsd is $8:\\n // fundingUsdForLongCollateral: $4\\n // fundingUsdForShortCollateral: $4\\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\\n //\\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\\n //\\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\\n //\\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\\n //\\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\\n //\\n // since both these values will be duplicated, the amount claimable would be:\\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\\n //\\n // due to these, the fundingUsd should be divided by the divisor\\n\\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\\n cache.fundingUsd = cache.fundingUsd / divisor;\\n\\n // split the fundingUsd value by long and short collateral\\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\\n // should be paid from long positions using short collateral\\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\\n if (result.longsPayShorts) {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\\n } else {\\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\\n }\\n\\n // calculate the change in funding amount per size values\\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\\n if (result.longsPayShorts) {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.long.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.long.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.shortOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.shortOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n } else {\\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\\n // positions only pay funding in the position's collateral token\\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.openInterest.short.longToken,\\n prices.longTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.openInterest.short.shortToken,\\n prices.shortTokenPrice.max,\\n true // roundUpMagnitude\\n );\\n\\n // positions receive funding in both the longToken and shortToken\\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForLongCollateral,\\n cache.longOpenInterest,\\n prices.longTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n\\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\\n cache.fundingUsdForShortCollateral,\\n cache.longOpenInterest,\\n prices.shortTokenPrice.max,\\n false // roundUpMagnitude\\n );\\n }\\n\\n return result;\\n }\\n\\n // @dev get the next funding factor per second\\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\\n // if it is bound by minFundingFactorPerSecond\\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\\n function getNextFundingFactorPerSecond(\\n DataStore dataStore,\\n address market,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest,\\n uint256 durationInSeconds\\n ) internal view returns (uint256, bool, int256) {\\n GetNextFundingFactorPerSecondCache memory cache;\\n\\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\\n\\n FundingConfigCache memory configCache;\\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\\n\\n // if the open interest difference is zero and adaptive funding\\n // is not enabled, then return zero as the funding factor\\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\\n return (0, true, 0);\\n }\\n\\n if (cache.totalOpenInterest == 0) {\\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\\n }\\n\\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\\n\\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\\n\\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\\n cache.fundingFactor = getFundingFactor(dataStore, market);\\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\\n\\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\\n fundingFactorPerSecond = maxFundingFactorPerSecond;\\n }\\n\\n return (\\n fundingFactorPerSecond,\\n longOpenInterest > shortOpenInterest,\\n 0\\n );\\n }\\n\\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\\n\\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\\n\\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\\n\\n // the default will be NoChange\\n FundingRateChangeType fundingRateChangeType;\\n\\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\\n\\n if (isSkewTheSameDirectionAsFunding) {\\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\\n // then the fundingRateChangeType would be NoChange\\n fundingRateChangeType = FundingRateChangeType.Decrease;\\n }\\n } else {\\n // if the skew has changed, then the funding should increase in the opposite direction\\n fundingRateChangeType = FundingRateChangeType.Increase;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\\n // increase funding rate\\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\\n\\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\\n if (longOpenInterest < shortOpenInterest) {\\n increaseValue = -increaseValue;\\n }\\n\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\\n }\\n\\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\\n\\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n } else {\\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\\n }\\n }\\n\\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\\n\\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n 0,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\\n cache.nextSavedFundingFactorPerSecond,\\n configCache.minFundingFactorPerSecond,\\n configCache.maxFundingFactorPerSecond\\n );\\n\\n return (\\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\\n cache.nextSavedFundingFactorPerSecond\\n );\\n }\\n\\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\\n function getFundingAmountPerSizeDelta(\\n uint256 fundingUsd,\\n uint256 openInterest,\\n uint256 tokenPrice,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\\n\\n uint256 fundingUsdPerSize = Precision.mulDiv(\\n fundingUsd,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n openInterest,\\n roundUpMagnitude\\n );\\n\\n if (roundUpMagnitude) {\\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\\n } else {\\n return fundingUsdPerSize / tokenPrice;\\n }\\n }\\n\\n // @dev update the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param longToken the market's long token\\n // @param shortToken the market's short token\\n // @param prices the prices of the market tokens\\n // @param isLong whether to update the long or short side\\n function updateCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) external {\\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n incrementCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market.marketToken,\\n isLong,\\n delta\\n );\\n\\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\\n\\n MarketEventUtils.emitBorrowing(\\n eventEmitter,\\n market.marketToken,\\n borrowingFactorPerSecond\\n );\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the trading market\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = MarketPrices(\\n oracle.getPrimaryPrice(_market.indexToken),\\n oracle.getPrimaryPrice(_market.longToken),\\n oracle.getPrimaryPrice(_market.shortToken)\\n );\\n\\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\\n }\\n\\n // @dev get the ratio of pnl to pool value\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n // @param maximize whether to maximize the factor\\n // @return (pnl of positions) / (long or short pool value)\\n function getPnlToPoolFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\\n\\n if (poolUsd == 0) {\\n return 0;\\n }\\n\\n // note that this PnL does not factor in the PnL from\\n // the pending price impact of positions\\n int256 pnl = getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n isLong,\\n maximize\\n );\\n\\n return Precision.toFactor(pnl, poolUsd);\\n }\\n\\n function validateOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\\n\\n if (openInterest > maxOpenInterest) {\\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\\n }\\n }\\n\\n // @dev validate that the pool amount is within the max allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param token the token to check\\n function validatePoolAmount(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\\n\\n if (poolAmount > maxPoolAmount) {\\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\\n }\\n }\\n\\n function validatePoolUsdForDeposit(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token,\\n uint256 tokenPrice\\n ) internal view {\\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\\n uint256 poolUsd = poolAmount * tokenPrice;\\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\\n\\n if (poolUsd > maxPoolUsd) {\\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev validate that the amount of tokens required to be reserved for open interest\\n // is below the configured threshold\\n // @param dataStore DataStore\\n // @param market the market values\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n function validateOpenInterestReserve(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view {\\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\\n // additionally, the shortToken may not be a stablecoin\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\\n\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd > maxReservedUsd) {\\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\\n }\\n }\\n\\n // @dev update the swap impact pool amount, if it is a positive impact amount\\n // cap the impact amount to the amount available in the swap impact pool\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to apply to\\n // @param token the token to apply to\\n // @param tokenPrice the price of the token\\n // @param priceImpactUsd the USD price impact\\n function applySwapImpactWithCap(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal returns (int256, uint256) {\\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\\n dataStore,\\n market,\\n token,\\n tokenPrice,\\n priceImpactUsd\\n );\\n\\n // if there is a positive impact, the impact pool amount should be reduced\\n // if there is a negative impact, the impact pool amount should be increased\\n applyDeltaToSwapImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n token,\\n -impactAmount\\n );\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n function getSwapImpactAmountWithCap(\\n DataStore dataStore,\\n address market,\\n address token,\\n Price.Props memory tokenPrice,\\n int256 priceImpactUsd\\n ) internal view returns (int256, uint256) {\\n int256 impactAmount;\\n uint256 cappedDiffUsd;\\n\\n if (priceImpactUsd > 0) {\\n // positive impact: minimize impactAmount, use tokenPrice.max\\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\\n\\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\\n if (impactAmount > maxImpactAmount) {\\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\\n impactAmount = maxImpactAmount;\\n }\\n } else {\\n // negative impact: maximize impactAmount, use tokenPrice.min\\n // round negative impactAmount up, this will be deducted from the user\\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\\n }\\n\\n return (impactAmount, cappedDiffUsd);\\n }\\n\\n // @dev get the funding amount to be deducted or distributed\\n //\\n // @param latestFundingAmountPerSize the latest funding amount per size\\n // @param positionFundingAmountPerSize the funding amount per size for the position\\n // @param positionSizeInUsd the position size in USD\\n // @param roundUpMagnitude whether the round up the result\\n //\\n // @return fundingAmount\\n function getFundingAmount(\\n uint256 latestFundingAmountPerSize,\\n uint256 positionFundingAmountPerSize,\\n uint256 positionSizeInUsd,\\n bool roundUpMagnitude\\n ) internal pure returns (uint256) {\\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\\n\\n // a user could avoid paying funding fees by continually updating the position\\n // before the funding fee becomes large enough to be chargeable\\n // to avoid this, funding fee amounts should be rounded up\\n //\\n // this could lead to large additional charges if the token has a low number of decimals\\n // or if the token's value is very high, so care should be taken to inform users of this\\n //\\n // if the calculation is for the claimable amount, the amount should be rounded down instead\\n\\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\\n // are stored based on FLOAT_PRECISION_SQRT values\\n return Precision.mulDiv(\\n positionSizeInUsd,\\n fundingDiffFactor,\\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\\n roundUpMagnitude\\n );\\n }\\n\\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\\n // has already been updated to the latest value\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @return the borrowing fees for a position\\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\\n // @param dataStore DataStore\\n // @param position Position.Props\\n // @param market the position's market\\n // @param prices the prices of the market tokens\\n // @return the borrowing fees for a position\\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n position.isLong()\\n );\\n\\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\\n }\\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\\n }\\n\\n // @dev get the total reserved USD required for positions\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the value for the long or short side\\n function getReservedUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd;\\n if (isLong) {\\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\\n // the available amount to be reserved would scale with the price of ETH\\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\\n // if the price of SOL increases more than the price of ETH, additional amounts would be\\n // automatically reserved\\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\\n } else {\\n // for shorts use the open interest as the reserved USD value\\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\\n // the available amount to be reserved would not change with the price of ETH\\n reservedUsd = getOpenInterest(dataStore, market, isLong);\\n }\\n\\n return reservedUsd;\\n }\\n\\n // @dev get the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0, 0);\\n }\\n\\n return (\\n true,\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\\n );\\n }\\n\\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\\n if (token != market.longToken && token != market.shortToken) {\\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\\n }\\n\\n return token == market.longToken;\\n }\\n\\n // @dev get the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param token the token to check\\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\\n }\\n\\n // @dev update the virtual inventory for swaps\\n // @param dataStore DataStore\\n // @param marketAddress the market to update\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForSwaps(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n address token,\\n int256 delta\\n ) internal returns (bool, uint256) {\\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\\n if (virtualMarketId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n bool isLongToken = getIsLongToken(market, token);\\n\\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev update the virtual inventory for positions\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param token the token to update\\n // @param delta the update amount\\n function applyDeltaToVirtualInventoryForPositions(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address token,\\n int256 delta\\n ) internal returns (bool, int256) {\\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\\n if (virtualTokenId == bytes32(0)) {\\n return (false, 0);\\n }\\n\\n int256 nextValue = dataStore.applyDeltaToInt(\\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\\n delta\\n );\\n\\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\\n\\n return (true, nextValue);\\n }\\n\\n // @dev get the open interest of a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market\\n ) internal view returns (uint256) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n return longOpenInterest + shortOpenInterest;\\n }\\n\\n // @dev get either the long or short open interest for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to get the long or short open interest\\n // @return the long or short open interest for a market\\n function getOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterest(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // this is used to divide the values of getPoolAmount and getOpenInterest\\n // if the longToken and shortToken are the same, then these values have to be divided by two\\n // to avoid double counting\\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\\n return longToken == shortToken ? 2 : 1;\\n }\\n\\n // @dev the long and short open interest in tokens for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\\n\\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\\n }\\n\\n // @dev the long and short open interest in tokens for a market based on the collateral token used\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateral token to check\\n // @param isLong whether to check the long or short side\\n function getOpenInterestInTokens(\\n DataStore dataStore,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 divisor\\n ) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the sum of open interest and pnl for a market\\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param indexTokenPrice the price of the index token\\n // @param isLong whether to check the long or short side\\n // @param maximize whether to maximize or minimize the value\\n // @return the sum of open interest and pnl for a market\\n function getOpenInterestWithPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n Price.Props memory indexTokenPrice,\\n bool isLong,\\n bool maximize\\n ) internal view returns (int256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\\n return Calc.sumReturnInt256(openInterest, pnl);\\n }\\n\\n // @dev get the max position impact factor for decreasing position\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isPositive whether the price impact is positive or negative\\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\\n\\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\\n }\\n\\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\\n\\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\\n maxPositiveImpactFactor = maxNegativeImpactFactor;\\n }\\n\\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\\n }\\n\\n // @dev get the max position impact factor for liquidations\\n // @param dataStore DataStore\\n // @param market the market to check\\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\\n }\\n\\n // @dev get the min collateral factor\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should always be larger than minCollateralFactorForLiquidation\\n // to ensure users cannot create immediately liquidatable positions.\\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\\n }\\n\\n // @dev get the min collateral factor for liquidation\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\\n }\\n\\n // @dev get the min collateral factor for open interest multiplier\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\\n }\\n\\n // @dev get the min collateral factor for open interest\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param openInterestDelta the change in open interest\\n // @param isLong whether it is for the long or short side\\n function getMinCollateralFactorForOpenInterest(\\n DataStore dataStore,\\n Market.Props memory market,\\n int256 openInterestDelta,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\\n return Precision.applyFactor(openInterest, multiplierFactor);\\n }\\n\\n // @dev get the total amount of position collateral for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the total amount of position collateral for a market\\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\\n }\\n\\n // @dev get the reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the reserve factor for a market\\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the open interest reserve factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the open interest reserve factor for a market\\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\\n }\\n\\n // @dev get the max pnl factor for a market\\n // @param dataStore DataStore\\n // @param pnlFactorType the type of the pnl factor\\n // @param market the market to check\\n // @param isLong whether to get the value for longs or shorts\\n // @return the max pnl factor for a market\\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\\n }\\n\\n // @dev get the min pnl factor after ADL\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\\n }\\n\\n // @dev get the funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding factor for a market\\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFactorKey(market));\\n }\\n\\n // @dev get the saved funding factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the saved funding factor for a market\\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\\n }\\n\\n // @dev set the saved funding factor\\n // @param dataStore DataStore\\n // @param market the market to set the funding factor for\\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\\n }\\n\\n // @dev get the funding exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @return the funding exponent factor for a market\\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\\n }\\n\\n // @dev get the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the funding fee amount per size for a market based on collateralToken\\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev get the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param collateralToken the collateralToken to check\\n // @param isLong whether to check the long or short size\\n // @return the claimable funding amount per size for a market based on collateralToken\\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\\n }\\n\\n // @dev apply delta to the funding fee amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToFundingFeeAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev apply delta to the claimable funding amount per size for a market\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param collateralToken the collateralToken to set\\n // @param isLong whether to set it for the long or short side\\n // @param delta the delta to increment by\\n function applyDeltaToClaimableFundingAmountPerSize(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address collateralToken,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.applyDeltaToUint(\\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\\n eventEmitter,\\n market,\\n collateralToken,\\n isLong,\\n delta,\\n nextValue\\n );\\n }\\n\\n // @dev get the number of seconds since funding was updated for a market\\n // @param market the market to check\\n // @return the number of seconds since funding was updated for a market\\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev get the borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing factor for a market\\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\\n }\\n\\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\\n }\\n\\n // @dev get the borrowing exponent factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the borrowing exponent factor for a market\\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\\n }\\n\\n // @dev get the cumulative borrowing factor for a market\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the cumulative borrowing factor for a market\\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\\n }\\n\\n // @dev increase the cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the market to increment the borrowing factor for\\n // @param isLong whether to increment the long or short side\\n // @param delta the increase amount\\n function incrementCumulativeBorrowingFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n bool isLong,\\n uint256 delta\\n ) internal {\\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\\n Keys.cumulativeBorrowingFactorKey(market, isLong),\\n delta\\n );\\n\\n MarketEventUtils.emitBorrowingFactorUpdated(\\n eventEmitter,\\n market,\\n isLong,\\n delta,\\n nextCumulativeBorrowingFactor\\n );\\n }\\n\\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the timestamp of when the cumulative borrowing factor was last updated\\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\\n }\\n\\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the number of seconds since the cumulative borrowing factor was last updated\\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\\n if (updatedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - updatedAt;\\n }\\n\\n // @dev update the total borrowing amount after a position changes size\\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\\n // @param dataStore DataStore\\n // @param market the market to update\\n // @param isLong whether to update the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function updateTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) external {\\n uint256 totalBorrowing = getNextTotalBorrowing(\\n dataStore,\\n market,\\n isLong,\\n prevPositionSizeInUsd,\\n prevPositionBorrowingFactor,\\n nextPositionSizeInUsd,\\n nextPositionBorrowingFactor\\n );\\n\\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\\n }\\n\\n // @dev get the next total borrowing amount after a position changes size\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param prevPositionSizeInUsd the previous position size in USD\\n // @param prevPositionBorrowingFactor the previous position borrowing factor\\n // @param nextPositionSizeInUsd the next position size in USD\\n // @param nextPositionBorrowingFactor the next position borrowing factor\\n function getNextTotalBorrowing(\\n DataStore dataStore,\\n address market,\\n bool isLong,\\n uint256 prevPositionSizeInUsd,\\n uint256 prevPositionBorrowingFactor,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal view returns (uint256) {\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\\n\\n return totalBorrowing;\\n }\\n\\n // @dev get the next cumulative borrowing factor\\n // @param dataStore DataStore\\n // @param prices the prices of the market tokens\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getNextCumulativeBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256, uint256, uint256) {\\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\\n }\\n\\n // @dev get the borrowing factor per second\\n // @param dataStore DataStore\\n // @param market the market to get the borrowing factor per second for\\n // @param prices the prices of the market tokens\\n // @param isLong whether to get the factor for the long or short side\\n function getBorrowingFactorPerSecond(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 reservedUsd = getReservedUsd(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n if (reservedUsd == 0) { return 0; }\\n\\n // check if the borrowing fee for the smaller side should be skipped\\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\\n // then the borrowing fee would be charged for both sides, this should be very rare\\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\\n if (skipBorrowingFeeForSmallerSide) {\\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\\n\\n // if getting the borrowing factor for longs and if the longOpenInterest\\n // is smaller than the shortOpenInterest, then return zero\\n if (isLong && longOpenInterest < shortOpenInterest) {\\n return 0;\\n }\\n\\n // if getting the borrowing factor for shorts and if the shortOpenInterest\\n // is smaller than the longOpenInterest, then return zero\\n if (!isLong && shortOpenInterest < longOpenInterest) {\\n return 0;\\n }\\n }\\n\\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\\n\\n if (poolUsd == 0) {\\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\\n }\\n\\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\\n\\n if (optimalUsageFactor != 0) {\\n return getKinkBorrowingFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd,\\n optimalUsageFactor\\n );\\n }\\n\\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\\n\\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\\n }\\n\\n function getKinkBorrowingFactor(\\n DataStore dataStore,\\n Market.Props memory market,\\n bool isLong,\\n uint256 reservedUsd,\\n uint256 poolUsd,\\n uint256 optimalUsageFactor\\n ) internal view returns (uint256) {\\n uint256 usageFactor = getUsageFactor(\\n dataStore,\\n market,\\n isLong,\\n reservedUsd,\\n poolUsd\\n );\\n\\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\\n\\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\\n usageFactor,\\n baseBorrowingFactor\\n );\\n\\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\\n uint256 diff = usageFactor - optimalUsageFactor;\\n\\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\\n uint256 additionalBorrowingFactorPerSecond;\\n\\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\\n }\\n\\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\\n\\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\\n }\\n\\n return borrowingFactorPerSecond;\\n }\\n\\n function distributePositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market\\n ) external {\\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n if (distributionAmount != 0) {\\n applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n -distributionAmount.toInt256()\\n );\\n\\n MarketEventUtils.emitPositionImpactPoolDistributed(\\n eventEmitter,\\n market,\\n distributionAmount,\\n nextPositionImpactPoolAmount\\n );\\n }\\n\\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\\n }\\n\\n function getNextPositionImpactPoolAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\\n\\n return nextPositionImpactPoolAmount;\\n }\\n\\n // @return (distributionAmount, nextPositionImpactPoolAmount)\\n function getPendingPositionImpactPoolDistributionAmount(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256, uint256) {\\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\\n\\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\\n\\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\\n\\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\\n\\n if (distributionAmount > maxDistributionAmount) {\\n distributionAmount = maxDistributionAmount;\\n }\\n\\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\\n }\\n\\n function getSecondsSincePositionImpactPoolDistributed(\\n DataStore dataStore,\\n address market\\n ) internal view returns (uint256) {\\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\\n if (distributedAt == 0) { return 0; }\\n return Chain.currentTimestamp() - distributedAt;\\n }\\n\\n // @dev get the total pending borrowing fees\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param isLong whether to check the long or short side\\n function getTotalPendingBorrowingFees(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong\\n ) internal view returns (uint256) {\\n uint256 openInterest = getOpenInterest(\\n dataStore,\\n market,\\n isLong\\n );\\n\\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\\n dataStore,\\n market,\\n prices,\\n isLong\\n );\\n\\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\\n\\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\\n }\\n\\n // @dev get the total borrowing value\\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\\n // for all positions of the market\\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @return the total borrowing value\\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\\n }\\n\\n // @dev set the total borrowing value\\n // @param dataStore DataStore\\n // @param market the market to set\\n // @param isLong whether to set the long or short side\\n // @param value the value to set to\\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\\n }\\n\\n // @dev convert a USD value to number of market tokens\\n // @param usdValue the input USD value\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the number of market tokens\\n function usdToMarketTokenAmount(\\n uint256 usdValue,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n // if the supply and poolValue is zero, use 1 USD as the token price\\n if (supply == 0 && poolValue == 0) {\\n return Precision.floatToWei(usdValue);\\n }\\n\\n // if the supply is zero and the poolValue is more than zero,\\n // then include the poolValue for the amount of tokens minted so that\\n // the market token price after mint would be 1 USD\\n if (supply == 0 && poolValue > 0) {\\n return Precision.floatToWei(poolValue + usdValue);\\n }\\n\\n // round market tokens down\\n return Precision.mulDiv(supply, usdValue, poolValue);\\n }\\n\\n // @dev convert a number of market tokens to its USD value\\n // @param marketTokenAmount the input number of market tokens\\n // @param poolValue the value of the pool\\n // @param supply the supply of market tokens\\n // @return the USD value of the market tokens\\n function marketTokenAmountToUsd(\\n uint256 marketTokenAmount,\\n uint256 poolValue,\\n uint256 supply\\n ) internal pure returns (uint256) {\\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\\n\\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n }\\n\\n // @dev validate that the specified market exists and is enabled\\n // @param dataStore DataStore\\n // @param market the market to check\\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\\n if (market.marketToken == address(0)) {\\n revert Errors.EmptyMarket();\\n }\\n\\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\\n if (isMarketDisabled) {\\n revert Errors.DisabledMarket(market.marketToken);\\n }\\n }\\n\\n // @dev validate that the positions can be opened in the given market\\n // @param market the market to check\\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\\n validateEnabledMarket(dataStore, market);\\n\\n if (isSwapOnlyMarket(market)) {\\n revert Errors.InvalidPositionMarket(market.marketToken);\\n }\\n }\\n\\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validatePositionMarket(dataStore, market);\\n }\\n\\n // @dev check if a market only supports swaps and not positions\\n // @param market the market to check\\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\\n return market.indexToken == address(0);\\n }\\n\\n // @dev check if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\\n return token == market.longToken || token == market.shortToken;\\n }\\n\\n // @dev validate if the given token is a collateral token of the market\\n // @param market the market to check\\n // @param token the token to check\\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\\n if (!isMarketCollateralToken(market, token)) {\\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\\n }\\n }\\n\\n // @dev get the enabled market, revert if the market does not exist or is not enabled\\n // @param dataStore DataStore\\n // @param marketAddress the address of the market\\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateEnabledMarket(dataStore, market);\\n return market;\\n }\\n\\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\\n validateSwapMarket(dataStore, market);\\n return market;\\n }\\n\\n // @dev get a list of market values based on an input array of market addresses\\n // @param swapPath list of market addresses\\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\\n }\\n\\n return markets;\\n }\\n\\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\\n if (swapPath.length > maxSwapPathLength) {\\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\\n }\\n\\n for (uint256 i; i < swapPath.length; i++) {\\n address marketAddress = swapPath[i];\\n validateSwapMarket(dataStore, marketAddress);\\n }\\n }\\n\\n // @dev validate that the pending pnl is below the allowed amount\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param prices the prices of the market tokens\\n // @param pnlFactorType the pnl factor type to check\\n function validateMaxPnl(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bytes32 pnlFactorTypeForLongs,\\n bytes32 pnlFactorTypeForShorts\\n ) internal view {\\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n true,\\n pnlFactorTypeForLongs\\n );\\n\\n if (isPnlFactorExceededForLongs) {\\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\\n }\\n\\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\\n dataStore,\\n market,\\n prices,\\n false,\\n pnlFactorTypeForShorts\\n );\\n\\n if (isPnlFactorExceededForShorts) {\\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\\n }\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param oracle Oracle\\n // @param market the market to check\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n IOracle oracle,\\n address market,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n Market.Props memory _market = getEnabledMarket(dataStore, market);\\n MarketPrices memory prices = getMarketPrices(oracle, _market);\\n\\n return isPnlFactorExceeded(\\n dataStore,\\n _market,\\n prices,\\n isLong,\\n pnlFactorType\\n );\\n }\\n\\n // @dev check if the pending pnl exceeds the allowed amount\\n // @param dataStore DataStore\\n // @param _market the market to check\\n // @param prices the prices of the market tokens\\n // @param isLong whether to check the long or short side\\n // @param pnlFactorType the pnl factor type to check\\n function isPnlFactorExceeded(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n bool isLong,\\n bytes32 pnlFactorType\\n ) internal view returns (bool, int256, uint256) {\\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\\n\\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\\n\\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\\n }\\n\\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\\n\\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\\n }\\n\\n function setUiFeeFactor(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address account,\\n uint256 uiFeeFactor\\n ) internal {\\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\\n\\n if (uiFeeFactor > maxUiFeeFactor) {\\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\\n }\\n\\n dataStore.setUint(\\n Keys.uiFeeFactorKey(account),\\n uiFeeFactor\\n );\\n\\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props[] memory markets\\n ) public view {\\n for (uint256 i; i < markets.length; i++) {\\n validateMarketTokenBalance(dataStore, markets[i]);\\n }\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n address _market\\n ) public view {\\n Market.Props memory market = getEnabledMarket(dataStore, _market);\\n validateMarketTokenBalance(dataStore, market);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market\\n ) public view {\\n validateMarketTokenBalance(dataStore, market, market.longToken);\\n\\n if (market.longToken == market.shortToken) {\\n return;\\n }\\n\\n validateMarketTokenBalance(dataStore, market, market.shortToken);\\n }\\n\\n function validateMarketTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view {\\n if (market.marketToken == address(0) || token == address(0)) {\\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\\n }\\n\\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\\n\\n if (balance < expectedMinBalance) {\\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\\n }\\n\\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\\n // hasn't been reduced yet\\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\\n // and validated separately\\n\\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\\n // longToken and shortToken\\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\\n\\n if (balance < collateralAmount) {\\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\\n }\\n\\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\\n\\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\\n // but this should be very rare\\n if (balance < claimableFundingFeeAmount) {\\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\\n }\\n }\\n\\n function getExpectedMinTokenBalance(\\n DataStore dataStore,\\n Market.Props memory market,\\n address token\\n ) internal view returns (uint256) {\\n GetExpectedMinTokenBalanceCache memory cache;\\n\\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\\n // for markets with the same long and short token\\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\\n\\n // funding fees are excluded from this summation as claimable funding fees\\n // are incremented without a corresponding decrease of the collateral of\\n // other positions, the collateral of other positions is decreased when\\n // those positions are updated\\n return\\n cache.poolAmount\\n + cache.swapImpactPoolAmount\\n + cache.claimableCollateralAmount\\n + cache.claimableFeeAmount\\n + cache.claimableUiFeeAmount\\n + cache.affiliateRewardAmount;\\n }\\n\\n function getProportionalAmounts(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketPrices memory prices,\\n uint256 totalUsd\\n ) internal view returns(uint256, uint256) {\\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\\n\\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\\n\\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\\n\\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\\n\\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\\n }\\n}\\n\",\"keccak256\":\"0xcfe9d22479ad521cd54cc6cf191e1b24f7482049a09f1d2e83d84c078c1e393e\",\"license\":\"BUSL-1.1\"},\"contracts/market/PositionImpactPoolUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport {DataStore} from \\\"../data/DataStore.sol\\\";\\nimport {Keys} from \\\"../data/Keys.sol\\\";\\nimport {Errors} from \\\"../error/Errors.sol\\\";\\nimport {EventEmitter} from \\\"../event/EventEmitter.sol\\\";\\nimport {Precision} from \\\"../utils/Precision.sol\\\";\\nimport {Market} from \\\"./Market.sol\\\";\\nimport {MarketEventUtils} from \\\"./MarketEventUtils.sol\\\";\\nimport {MarketPoolValueInfo} from \\\"./MarketPoolValueInfo.sol\\\";\\nimport {MarketStoreUtils} from \\\"./MarketStoreUtils.sol\\\";\\nimport {MarketToken} from \\\"./MarketToken.sol\\\";\\nimport {MarketUtils} from \\\"./MarketUtils.sol\\\";\\nimport {SafeCast} from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IOracle } from \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../position/PositionUtils.sol\\\";\\n\\nlibrary PositionImpactPoolUtils {\\n using SignedMath for int256;\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n using SafeERC20 for IERC20;\\n\\n using Market for Market.Props;\\n\\n // @dev withdraw funds from the position impact pool while maintaining GM token price\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param market the trading market\\n // @param receiver the address to receive the withdrawn funds\\n // @param amount the amount to withdraw\\n // @param oracle - oracle to fetch the market prices\\n function withdrawFromPositionImpactPool(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address receiver,\\n uint256 amount\\n ) external {\\n require(amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n MarketUtils.distributePositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market\\n );\\n\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\\n dataStore,\\n marketProps,\\n prices.indexTokenPrice,\\n prices.longTokenPrice,\\n prices.shortTokenPrice,\\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\\n false\\n );\\n\\n if (poolValueInfo.poolValue <= 0) {\\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\\n }\\n\\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\\n\\n // if there is a positive totalPendingImpactAmount, that means that the\\n // excess should be covered by the position impact pool, so subtract this\\n // from the impactPoolAmount that can be withdrawn\\n // lent amount is not considered here, because if there is a lent amount\\n // we assume that the position impact would be zero\\n if (totalPendingImpactAmount > 0) {\\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\\n }\\n\\n if (adjustedImpactPoolAmount < amount) {\\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\\n }\\n\\n MarketUtils.applyDeltaToPositionImpactPool(\\n dataStore,\\n eventEmitter,\\n market,\\n - amount.toInt256()\\n );\\n\\n // Calculate amount of tokens to withdraw:\\n // We want to withdraw long and short tokens from the pool\\n // at the current pool token ratio\\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\\n dataStore,\\n marketProps,\\n prices,\\n amount * prices.indexTokenPrice.min\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n - longTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n - shortTokenWithdrawalAmount.toInt256()\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.longToken,\\n receiver,\\n longTokenWithdrawalAmount\\n );\\n\\n MarketToken(payable(market)).transferOut(\\n marketProps.shortToken,\\n receiver,\\n shortTokenWithdrawalAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\\n eventEmitter,\\n market,\\n receiver,\\n amount\\n );\\n }\\n\\n function reduceLentAmount(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n IOracle oracle,\\n address market,\\n address fundingAccount,\\n uint256 reductionAmount\\n ) external {\\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\\n\\n PositionUtils.updateFundingAndBorrowingState(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n prices\\n );\\n\\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\\n\\n if (reductionAmount > lentAmount) {\\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\\n }\\n\\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\\n\\n if (longTokenAmount > 0) {\\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\\n }\\n\\n if (shortTokenAmount > 0) {\\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\\n }\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.longToken,\\n longTokenAmount.toInt256()\\n );\\n\\n MarketUtils.applyDeltaToPoolAmount(\\n dataStore,\\n eventEmitter,\\n marketProps,\\n marketProps.shortToken,\\n shortTokenAmount.toInt256()\\n );\\n\\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n MarketEventUtils.emitLentImpactAmountReduction(\\n eventEmitter,\\n market,\\n fundingAccount,\\n longTokenAmount,\\n shortTokenAmount,\\n reductionAmount\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe74b2dfdd27d92eb33535d5c5fe4af456d05c180d17d8252f5728c62dd1293b0\",\"license\":\"BUSL-1.1\"},\"contracts/mock/Multicall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title Multicall3\\n/// @notice Aggregate results from multiple function calls\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract Multicall3 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked { ++i; }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i; i < length;) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked { valAccumulator += val; }\\n (result.success, result.returnData) = calli.target.call{value: val}(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked { ++i; }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x403295008f09f7f5911396b6243d95bd4084e8f6e085af2b958a4af64c29e07c\",\"license\":\"MIT\"},\"contracts/multichain/MultichainVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n/**\\n * @title MultichainVault\\n * @dev Vault for crosschain deposits\\n */\\ncontract MultichainVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0xf3dc92390fd6ebe2f71535aa889e5fe258d73e6a8cc8d0b74fe9f94e3aae109b\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/ChainlinkPriceFeedUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./IPriceFeed.sol\\\";\\n\\n// @title ChainlinkPriceFeedProviderUtils\\n// @dev Library for Chainlink price feed\\nlibrary ChainlinkPriceFeedUtils {\\n // there is a small risk of stale pricing due to latency in price updates or if the chain is down\\n // this is meant to be for temporary use until low latency price feeds are supported for all tokens\\n function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {\\n address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));\\n if (priceFeedAddress == address(0)) {\\n return (false, 0);\\n }\\n\\n IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);\\n\\n (\\n /* uint80 roundID */,\\n int256 _price,\\n /* uint256 startedAt */,\\n uint256 timestamp,\\n /* uint80 answeredInRound */\\n ) = priceFeed.latestRoundData();\\n\\n if (_price <= 0) {\\n revert Errors.InvalidFeedPrice(token, _price);\\n }\\n\\n uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));\\n if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {\\n revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);\\n }\\n\\n uint256 price = SafeCast.toUint256(_price);\\n uint256 precision = getPriceFeedMultiplier(dataStore, token);\\n\\n uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);\\n\\n return (true, adjustedPrice);\\n }\\n\\n // @dev get the multiplier value to convert the external price feed price to the price of 1 unit of the token\\n // represented with 30 decimals\\n // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of\\n // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)\\n // if the external price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8)\\n // in this case the priceFeedMultiplier should be 10 ^ 46\\n // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24)\\n // formula for decimals for price feed multiplier: 60 - (external price feed decimals) - (token decimals)\\n //\\n // @param dataStore DataStore\\n // @param token the token to get the price feed multiplier for\\n // @return the price feed multipler\\n function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {\\n uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));\\n\\n if (multiplier == 0) {\\n revert Errors.EmptyChainlinkPriceFeedMultiplier(token);\\n }\\n\\n return multiplier;\\n }\\n}\\n\",\"keccak256\":\"0xf2abeec57d21410a8306356562077b0aedb77f15be6a5d1451c915c0c20b2fe6\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"./OracleUtils.sol\\\";\\n\\ninterface IOracle {\\n function minTimestamp() external view returns (uint256);\\n function maxTimestamp() external view returns (uint256);\\n function dataStore() external view returns (DataStore);\\n function eventEmitter() external view returns (EventEmitter);\\n\\n function validateSequencerUp() external view;\\n function setPrices(OracleUtils.SetPricesParams memory params) external;\\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\\n function setPrimaryPrice(address token, Price.Props memory price) external;\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\\n function clearAllPrices() external;\\n function getTokensWithPricesCount() external view returns (uint256);\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external returns (OracleUtils.ValidatedPrice[] memory);\\n}\\n\",\"keccak256\":\"0x79d6b94a3a30f79c0c3c31a1304ef08f7a5fe0fd1af50d27899e56b0983aaa2f\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OracleUtils.sol\\\";\\n\\n// @title IOracleProvider\\n// @dev Interface for an oracle provider\\ninterface IOracleProvider {\\n function getOraclePrice(\\n address token,\\n bytes memory data\\n ) external returns (OracleUtils.ValidatedPrice memory);\\n\\n /// @dev for all oracle providers besides ChainlinkPriceFeedProvider\\n function shouldAdjustTimestamp() external pure returns (bool);\\n\\n /// @dev for ChainlinkPriceFeedProvider\\n function isChainlinkOnChainProvider() external pure returns (bool);\\n}\\n\",\"keccak256\":\"0x8d58f6373f8894c71e559e845db06043047c4ccdf9fac827f8cdf41044b3b1f6\",\"license\":\"MIT\"},\"contracts/oracle/IPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n// @title IPriceFeed\\n// @dev Interface for a price feed\\ninterface IPriceFeed {\\n function latestRoundData() external view returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function description() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x5474d86a80fde875ffd0b52d2806554b32bf10c33553ecae7de1f82400bcf5b6\",\"license\":\"MIT\"},\"contracts/oracle/Oracle.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport { AggregatorV2V3Interface } from \\\"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\\\";\\n\\nimport \\\"../role/RoleModule.sol\\\";\\n\\nimport \\\"./OracleUtils.sol\\\";\\nimport \\\"./IOracle.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\nimport \\\"./ChainlinkPriceFeedUtils.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\nimport \\\"../chain/Chain.sol\\\";\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\nimport \\\"../utils/Uint256Mask.sol\\\";\\n\\n// @title Oracle\\n// @dev Contract to validate and store signed values\\n// Some calculations e.g. calculating the size in tokens for a position\\n// may not work with zero / negative prices\\n// as a result, zero / negative prices are considered empty / invalid\\n// A market may need to be manually settled in this case\\ncontract Oracle is IOracle, RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using Price for Price.Props;\\n using Uint256Mask for Uint256Mask.Mask;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n DataStore public immutable dataStore;\\n EventEmitter public immutable eventEmitter;\\n AggregatorV2V3Interface public immutable sequencerUptimeFeed;\\n\\n // tokensWithPrices stores the tokens with prices that have been set\\n // this is used in clearAllPrices to help ensure that all token prices\\n // set in setPrices are cleared after use\\n EnumerableSet.AddressSet internal tokensWithPrices;\\n mapping(address => Price.Props) public primaryPrices;\\n\\n uint256 public minTimestamp;\\n uint256 public maxTimestamp;\\n\\n constructor(\\n RoleStore _roleStore,\\n DataStore _dataStore,\\n EventEmitter _eventEmitter,\\n AggregatorV2V3Interface _sequencerUptimeFeed\\n ) RoleModule(_roleStore) {\\n dataStore = _dataStore;\\n eventEmitter = _eventEmitter;\\n sequencerUptimeFeed = _sequencerUptimeFeed;\\n }\\n\\n // this can be used to help ensure that on-chain prices are updated\\n // before actions dependent on those on-chain prices are allowed\\n // additionally, this can also be used to provide a grace period for\\n // users to top up collateral before liquidations occur\\n function validateSequencerUp() public view {\\n if (address(sequencerUptimeFeed) == address(0)) {\\n return;\\n }\\n\\n (\\n /*uint80 roundID*/,\\n int256 answer,\\n uint256 startedAt,\\n /*uint256 updatedAt*/,\\n /*uint80 answeredInRound*/\\n ) = sequencerUptimeFeed.latestRoundData();\\n\\n // answer == 0: sequencer is up\\n // answer == 1: sequencer is down\\n bool isSequencerUp = answer == 0;\\n if (!isSequencerUp) {\\n revert Errors.SequencerDown();\\n }\\n\\n uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);\\n\\n // ensure the grace duration has passed after the\\n // sequencer is back up.\\n uint256 timeSinceUp = block.timestamp - startedAt;\\n if (timeSinceUp <= sequencerGraceDuration) {\\n revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);\\n }\\n }\\n\\n function setPrices(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);\\n\\n _setPrices(prices);\\n }\\n\\n function setPricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) external onlyController {\\n validateSequencerUp();\\n\\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);\\n\\n _setPrices(prices);\\n }\\n\\n // @dev set the primary price\\n // @param token the token to set the price for\\n // @param price the price value to set to\\n function setPrimaryPrice(address token, Price.Props memory price) external onlyController {\\n _setPrimaryPrice(token, price);\\n }\\n\\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n // @dev clear all prices\\n function clearAllPrices() external onlyController {\\n uint256 length = tokensWithPrices.length();\\n for (uint256 i; i < length; i++) {\\n address token = tokensWithPrices.at(0);\\n _removePrimaryPrice(token);\\n }\\n\\n minTimestamp = 0;\\n maxTimestamp = 0;\\n }\\n\\n // @dev get the length of tokensWithPrices\\n // @return the length of tokensWithPrices\\n function getTokensWithPricesCount() external view returns (uint256) {\\n return tokensWithPrices.length();\\n }\\n\\n // @dev get the tokens of tokensWithPrices for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the tokens of tokensWithPrices for the specified indexes\\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {\\n return tokensWithPrices.valuesAt(start, end);\\n }\\n\\n // @dev get the primary price of a token\\n // @param token the token to get the price for\\n // @return the primary price of a token\\n function getPrimaryPrice(address token) external view returns (Price.Props memory) {\\n if (token == address(0)) { return Price.Props(0, 0); }\\n\\n Price.Props memory price = primaryPrices[token];\\n if (price.isEmpty()) {\\n revert Errors.EmptyPrimaryPrice(token);\\n }\\n\\n return price;\\n }\\n\\n function validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {\\n return _validatePrices(params, forAtomicAction);\\n }\\n\\n // @dev validate and set prices\\n // @param params OracleUtils.SetPricesParams\\n function _setPrices(\\n OracleUtils.ValidatedPrice[] memory prices\\n ) internal {\\n // in case of gasless relay the prices are not required if there is no need to swap fee tokens\\n if (prices.length == 0) {\\n return;\\n }\\n\\n if (tokensWithPrices.length() != 0) {\\n revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());\\n }\\n\\n uint256 _minTimestamp = prices[0].timestamp;\\n uint256 _maxTimestamp = prices[0].timestamp;\\n\\n for (uint256 i; i < prices.length; i++) {\\n OracleUtils.ValidatedPrice memory validatedPrice = prices[i];\\n\\n _setPrimaryPrice(validatedPrice.token, Price.Props(\\n validatedPrice.min,\\n validatedPrice.max\\n ));\\n\\n if (validatedPrice.timestamp < _minTimestamp) {\\n _minTimestamp = validatedPrice.timestamp;\\n }\\n\\n if (validatedPrice.timestamp > _maxTimestamp) {\\n _maxTimestamp = validatedPrice.timestamp;\\n }\\n\\n _emitOraclePriceUpdated(\\n validatedPrice.token,\\n validatedPrice.min,\\n validatedPrice.max,\\n validatedPrice.timestamp,\\n validatedPrice.provider\\n );\\n }\\n\\n uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);\\n if (_maxTimestamp - _minTimestamp > maxRange) {\\n revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);\\n }\\n\\n minTimestamp = _minTimestamp;\\n maxTimestamp = _maxTimestamp;\\n }\\n\\n function _validatePrices(\\n OracleUtils.SetPricesParams memory params,\\n bool forAtomicAction\\n ) internal returns (OracleUtils.ValidatedPrice[] memory) {\\n if (params.tokens.length != params.providers.length) {\\n revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);\\n }\\n\\n if (params.tokens.length != params.data.length) {\\n revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);\\n }\\n\\n OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);\\n\\n if (params.tokens.length == 0) {\\n return prices;\\n }\\n\\n uint256 maxPriceAge = forAtomicAction ? dataStore.getUint(Keys.MAX_ATOMIC_ORACLE_PRICE_AGE) : dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);\\n uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);\\n\\n for (uint256 i; i < params.tokens.length; i++) {\\n address _provider = params.providers[i];\\n IOracleProvider provider = IOracleProvider(_provider);\\n\\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(_provider))) {\\n revert Errors.InvalidOracleProvider(_provider);\\n }\\n\\n address token = params.tokens[i];\\n\\n bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(_provider));\\n\\n // if the action is atomic then only validate that the provider is an\\n // atomic provider\\n // else, validate that the provider matches the oracleProviderForToken\\n //\\n // since for atomic actions, any atomic provider can be used, it is\\n // recommended that only one atomic provider is configured per token\\n // otherwise there is a risk that if there is a difference in pricing\\n // between atomic oracle providers for a token, a user could use that\\n // to gain a profit by alternating actions between the two atomic\\n // providers\\n if (forAtomicAction) {\\n if (!isAtomicProvider) {\\n revert Errors.NonAtomicOracleProvider(_provider);\\n }\\n } else {\\n address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(address(this), token));\\n if (_provider != expectedProvider) {\\n revert Errors.InvalidOracleProviderForToken(_provider, expectedProvider);\\n }\\n }\\n\\n bytes memory data = params.data[i];\\n\\n OracleUtils.ValidatedPrice memory validatedPrice = provider.getOraclePrice(\\n token,\\n data\\n );\\n\\n // for atomic providers, the timestamp will be the current block's timestamp\\n // the timestamp should not be adjusted\\n if (provider.shouldAdjustTimestamp()) {\\n uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(_provider, token));\\n validatedPrice.timestamp -= timestampAdjustment;\\n }\\n\\n if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {\\n revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());\\n }\\n\\n if (!provider.isChainlinkOnChainProvider()) {\\n (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\\n\\n if (hasRefPrice) {\\n _validateRefPrice(\\n token,\\n validatedPrice.min,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n\\n _validateRefPrice(\\n token,\\n validatedPrice.max,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n prices[i] = validatedPrice;\\n }\\n\\n return prices;\\n }\\n\\n function _validateRefPrice(\\n address token,\\n uint256 price,\\n uint256 refPrice,\\n uint256 maxRefPriceDeviationFactor\\n ) internal pure {\\n uint256 diff = Calc.diff(price, refPrice);\\n uint256 diffFactor = Precision.toFactor(diff, refPrice);\\n\\n if (diffFactor > maxRefPriceDeviationFactor) {\\n revert Errors.MaxRefPriceDeviationExceeded(\\n token,\\n price,\\n refPrice,\\n maxRefPriceDeviationFactor\\n );\\n }\\n }\\n\\n function _setPrimaryPrice(address token, Price.Props memory price) internal {\\n if (price.min > price.max) {\\n revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);\\n }\\n\\n Price.Props memory existingPrice = primaryPrices[token];\\n\\n if (!existingPrice.isEmpty()) {\\n revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);\\n }\\n\\n primaryPrices[token] = price;\\n tokensWithPrices.add(token);\\n }\\n\\n function _removePrimaryPrice(address token) internal {\\n delete primaryPrices[token];\\n tokensWithPrices.remove(token);\\n }\\n\\n function _emitOraclePriceUpdated(\\n address token,\\n uint256 minPrice,\\n uint256 maxPrice,\\n uint256 timestamp,\\n address provider\\n ) internal {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(2);\\n eventData.addressItems.setItem(0, \\\"token\\\", token);\\n eventData.addressItems.setItem(1, \\\"provider\\\", provider);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"minPrice\\\", minPrice);\\n eventData.uintItems.setItem(1, \\\"maxPrice\\\", maxPrice);\\n eventData.uintItems.setItem(2, \\\"timestamp\\\", timestamp);\\n\\n eventEmitter.emitEventLog1(\\n \\\"OraclePriceUpdate\\\",\\n Cast.toBytes32(token),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x37cac3c6590c434acbf8b391b6a6fb875ecb671e2859f473d17d5afe7e1e38e5\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IOracle.sol\\\";\\n\\n// @title OracleModule\\n// @dev Provides convenience functions for interacting with the Oracle\\ncontract OracleModule {\\n IOracle public immutable oracle;\\n\\n constructor(IOracle _oracle) {\\n oracle = _oracle;\\n }\\n\\n // @dev sets oracle prices, perform any additional tasks required,\\n // and clear the oracle prices after\\n //\\n // care should be taken to avoid re-entrancy while using this call\\n // since re-entrancy could allow functions to be called with prices\\n // meant for a different type of transaction\\n // the tokensWithPrices.length check in oracle.setPrices should help\\n // mitigate this\\n //\\n // @param params OracleUtils.SetPricesParams\\n modifier withOraclePrices(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPrices(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n modifier withOraclePricesForAtomicAction(\\n OracleUtils.SetPricesParams memory params\\n ) {\\n oracle.setPricesForAtomicAction(params);\\n _;\\n oracle.clearAllPrices();\\n }\\n\\n // @dev set oracle prices for a simulation\\n // tokensWithPrices is not set in this function\\n // it is possible for withSimulatedOraclePrices to be called and a function\\n // using withOraclePrices to be called after\\n // or for a function using withOraclePrices to be called and withSimulatedOraclePrices\\n // called after\\n // this should not cause an issue because this transaction should always revert\\n // and any state changes based on simulated prices as well as the setting of simulated\\n // prices should not be persisted\\n // @param params OracleUtils.SimulatePricesParams\\n modifier withSimulatedOraclePrices(\\n OracleUtils.SimulatePricesParams memory params\\n ) {\\n if (params.primaryTokens.length != params.primaryPrices.length) {\\n revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);\\n }\\n\\n for (uint256 i; i < params.primaryTokens.length; i++) {\\n address token = params.primaryTokens[i];\\n Price.Props memory price = params.primaryPrices[i];\\n oracle.setPrimaryPrice(token, price);\\n }\\n\\n oracle.setTimestamps(params.minTimestamp, params.maxTimestamp);\\n\\n _;\\n\\n revert Errors.EndOfOracleSimulation();\\n }\\n}\\n\",\"keccak256\":\"0x19e4098e3f037bb6e1deb3a93aa98d42ceac46bf10553fb9aff784f9fbbc16ff\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../role/RoleModule.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\n// @title OracleStore\\n// @dev Stores the list of oracle signers\\ncontract OracleStore is RoleModule {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n EventEmitter public immutable eventEmitter;\\n\\n EnumerableSet.AddressSet internal signers;\\n\\n constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {\\n eventEmitter = _eventEmitter;\\n }\\n\\n // @dev adds a signer\\n // @param account address of the signer to add\\n function addSigner(address account) external onlyController {\\n signers.add(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerAdded\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev removes a signer\\n // @param account address of the signer to remove\\n function removeSigner(address account) external onlyController {\\n signers.remove(account);\\n\\n EventUtils.EventLogData memory eventData;\\n eventData.addressItems.initItems(1);\\n eventData.addressItems.setItem(0, \\\"account\\\", account);\\n\\n eventEmitter.emitEventLog1(\\n \\\"SignerRemoved\\\",\\n Cast.toBytes32(account),\\n eventData\\n );\\n }\\n\\n // @dev get the total number of signers\\n // @return the total number of signers\\n function getSignerCount() external view returns (uint256) {\\n return signers.length();\\n }\\n\\n // @dev get the signer at the specified index\\n // @param index the index of the signer to get\\n // @return the signer at the specified index\\n function getSigner(uint256 index) external view returns (address) {\\n return signers.at(index);\\n }\\n\\n // @dev get the signers for the specified indexes\\n // @param start the start index, the value for this index will be included\\n // @param end the end index, the value for this index will not be included\\n // @return the signers for the specified indexes\\n function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {\\n return signers.valuesAt(start, end);\\n }\\n}\\n\",\"keccak256\":\"0x5b9c2917e29aa696a8385f9f8b6a0cd0f1ef9a0b08d8096a2f19367e89cc09e7\",\"license\":\"BUSL-1.1\"},\"contracts/oracle/OracleUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Array.sol\\\";\\nimport \\\"../price/Price.sol\\\";\\n\\n// @title OracleUtils\\n// @dev Library for oracle functions\\nlibrary OracleUtils {\\n using Array for uint256[];\\n\\n struct SetPricesParams {\\n address[] tokens;\\n address[] providers;\\n bytes[] data;\\n }\\n\\n struct ValidatedPrice {\\n address token;\\n uint256 min;\\n uint256 max;\\n uint256 timestamp;\\n address provider;\\n }\\n\\n struct SimulatePricesParams {\\n address[] primaryTokens;\\n Price.Props[] primaryPrices;\\n uint256 minTimestamp;\\n uint256 maxTimestamp;\\n }\\n\\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\\n if (isOracleTimestampError(errorSelector)) {\\n return true;\\n }\\n\\n if (isEmptyPriceError(errorSelector)) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n\\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\\n return true;\\n }\\n\\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\\n return true;\\n }\\n\\n return false;\\n }\\n}\\n\",\"keccak256\":\"0x76cec78707c742efd9b6f8e50a3ab441fd588ac226d5ae7a707ea8fdff0da09c\",\"license\":\"BUSL-1.1\"},\"contracts/order/BaseOrderUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Order.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../referral/IReferralStorage.sol\\\";\\n\\nimport \\\"../order/OrderVault.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../position/Position.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../swap/ISwapHandler.sol\\\";\\n\\nimport \\\"../multichain/MultichainVault.sol\\\";\\n\\n// @title Order\\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\\n// DecreaseOrderUtils, SwapOrderUtils\\nlibrary BaseOrderUtils {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n using Order for Order.Props;\\n using Price for Price.Props;\\n\\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\\n // too deep errors\\n //\\n // @param contracts ExecuteOrderParamsContracts\\n // @param key the key of the order to execute\\n // @param order the order to execute\\n // @param swapPathMarkets the market values of the markets in the swapPath\\n // @param minOracleTimestamp the min oracle timestamp\\n // @param maxOracleTimestamp the max oracle timestamp\\n // @param market market values of the trading market\\n // @param keeper the keeper sending the transaction\\n // @param startingGas the starting gas\\n // @param secondaryOrderType the secondary order type\\n struct ExecuteOrderParams {\\n ExecuteOrderParamsContracts contracts;\\n bytes32 key;\\n Order.Props order;\\n Market.Props[] swapPathMarkets;\\n uint256 minOracleTimestamp;\\n uint256 maxOracleTimestamp;\\n Market.Props market;\\n address keeper;\\n uint256 startingGas;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param orderVault OrderVault\\n // @param oracle Oracle\\n // @param swapHandler ISwapHandler\\n // @param referralStorage IReferralStorage\\n struct ExecuteOrderParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n MultichainVault multichainVault;\\n OrderVault orderVault;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct GetExecutionPriceCache {\\n uint256 price;\\n uint256 executionPrice;\\n int256 adjustedPriceImpactUsd;\\n }\\n\\n // @dev validate the price for increase / decrease orders based on the triggerPrice\\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\\n //\\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\\n //\\n // however, this may lead to gaming issues, an example:\\n // - the current price is $2020\\n // - a user has a long position and creates a stop-loss decrease order for < $2010\\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\\n // to be frozen / unexecutable by manipulating state or otherwise\\n // - then if price decreases to $2000, and the user is able to manipulate state such that\\n // the order becomes executable with $2010 being used as the price instead\\n // - then the user would be able to perform the swap at a higher price than should possible\\n //\\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\\n // directional price movement, fees and price impact should help a bit with this, but there\\n // still may be some probability of success\\n //\\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\\n // should lead to similar order execution prices with reduced gaming risks\\n //\\n // if an order is frozen, the frozen order keepers should use the most recent price for order\\n // execution instead\\n //\\n // @param oracle Oracle\\n // @param indexToken the index token\\n // @param orderType the order type\\n // @param triggerPrice the order's triggerPrice\\n // @param isLong whether the order is for a long or short\\n function validateOrderTriggerPrice(\\n IOracle oracle,\\n address indexToken,\\n Order.OrderType orderType,\\n uint256 triggerPrice,\\n bool isLong\\n ) internal view {\\n if (\\n Order.isSwapOrder(orderType) ||\\n Order.isMarketOrder(orderType) ||\\n Order.isLiquidationOrder(orderType)\\n ) {\\n return;\\n }\\n\\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\\n\\n // for limit increase long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for limit increase short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.LimitIncrease) {\\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop increase long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n // for stop increase short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n if (orderType == Order.OrderType.StopIncrease) {\\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for limit decrease long positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for limit decrease short positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.LimitDecrease) {\\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n // for stop-loss decrease long positions:\\n // - the order should be executed when the oracle price is <= triggerPrice\\n // - primaryPrice.min should be used for the oracle price\\n // for stop-loss decrease short positions:\\n // - the order should be executed when the oracle price is >= triggerPrice\\n // - primaryPrice.max should be used for the oracle price\\n if (orderType == Order.OrderType.StopLossDecrease) {\\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\\n\\n if (!ok) {\\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\\n }\\n\\n return;\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(orderType));\\n }\\n\\n function validateOrderValidFromTime(\\n Order.OrderType orderType,\\n uint256 validFromTime\\n ) internal view {\\n if (Order.isMarketOrder(orderType)) {\\n return;\\n }\\n\\n uint256 currentTimestamp = Chain.currentTimestamp();\\n if (validFromTime > currentTimestamp) {\\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\\n }\\n }\\n\\n function getExecutionPriceForIncrease(\\n uint256 sizeDeltaUsd,\\n uint256 sizeDeltaInTokens,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n if (sizeDeltaInTokens == 0) {\\n revert Errors.EmptySizeDeltaInTokens();\\n }\\n\\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\\n\\n // increase order:\\n // - long: executionPrice should be smaller than acceptablePrice\\n // - short: executionPrice should be larger than acceptablePrice\\n if (\\n (isLong && executionPrice <= acceptablePrice) ||\\n (!isLong && executionPrice >= acceptablePrice)\\n ) {\\n return executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\\n }\\n\\n function getExecutionPriceForDecrease(\\n Price.Props memory indexTokenPrice,\\n uint256 positionSizeInUsd,\\n uint256 positionSizeInTokens,\\n uint256 sizeDeltaUsd,\\n int256 priceImpactUsd,\\n uint256 acceptablePrice,\\n bool isLong\\n ) internal pure returns (uint256) {\\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\\n // This does NOT include capping based on the price impact pool balance, so the computed\\n // executionPrice may not reflect the actual executionPrice experienced by the order.\\n // Consumers of this function should be aware that the final execution price may differ\\n // if further capping is applied elsewhere based on the impact pool.\\n GetExecutionPriceCache memory cache;\\n\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n cache.price = indexTokenPrice.pickPrice(!isLong);\\n cache.executionPrice = cache.price;\\n\\n // using closing of long positions as an example\\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\\n // priceImpactUsd should adjust the execution price such that:\\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\\n //\\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n //\\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\\n //\\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\\n // realizedPnl based on price, without price impact: 0\\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\\n\\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\\n // a negative adjustedPriceImpactUsd would increase the executionPrice\\n\\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\\n // increase long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // increase short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\\n\\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\\n // decrease long order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // decrease short order:\\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\\n // adjust price by price impact\\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\\n\\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\\n int256 _executionPrice = cache.price.toInt256() + adjustment;\\n\\n if (_executionPrice < 0) {\\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\\n }\\n\\n cache.executionPrice = _executionPrice.toUint256();\\n }\\n\\n // decrease order:\\n // - long: executionPrice should be larger than acceptablePrice\\n // - short: executionPrice should be smaller than acceptablePrice\\n if (\\n (isLong && cache.executionPrice >= acceptablePrice) ||\\n (!isLong && cache.executionPrice <= acceptablePrice)\\n ) {\\n return cache.executionPrice;\\n }\\n\\n // the validateOrderTriggerPrice function should have validated if the price fulfills\\n // the order's trigger price\\n //\\n // for decrease orders, the price impact should already be capped, so if the user\\n // had set an acceptable price within the range of the capped price impact, then\\n // the order should be fulfillable at the acceptable price\\n //\\n // for increase orders, the negative price impact is not capped\\n //\\n // for both increase and decrease orders, if it is due to price impact that the\\n // order cannot be fulfilled then the order should be frozen\\n //\\n // this is to prevent gaming by manipulation of the price impact value\\n //\\n // usually it should be costly to game the price impact value\\n // however, for certain cases, e.g. a user already has a large position opened\\n // the user may create limit orders that would only trigger after they close\\n // their position, this gives the user the option to cancel the pending order if\\n // prices do not move in their favour or to close their position and let the order\\n // execute if prices move in their favour\\n //\\n // it may also be possible for users to prevent the execution of orders from other users\\n // by manipulating the price impact, though this should be costly\\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\\n }\\n\\n // @dev validate that an order exists\\n // @param order the order to check\\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\\n if (order.account() == address(0)) {\\n revert Errors.EmptyOrder();\\n }\\n\\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\\n revert Errors.EmptyOrder();\\n }\\n }\\n\\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\\n if (Order.isDecreaseOrder(order.orderType())) {\\n return Position.getPositionKey(\\n order.account(),\\n order.market(),\\n order.initialCollateralToken(),\\n order.isLong()\\n );\\n }\\n\\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\\n }\\n}\\n\",\"keccak256\":\"0xc14362ae464283d2ad0ab6dfa6cd49f4412cbbd368234bbf8147d9a039c684bc\",\"license\":\"BUSL-1.1\"},\"contracts/order/Order.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../chain/Chain.sol\\\";\\n\\n// @title Order\\n// @dev Struct for orders\\nlibrary Order {\\n using Order for Props;\\n\\n enum OrderType {\\n // @dev MarketSwap: swap token A to token B at the current market price\\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\\n MarketSwap,\\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\\n LimitSwap,\\n // @dev MarketIncrease: increase position at the current market price\\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\\n MarketIncrease,\\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitIncrease,\\n // @dev MarketDecrease: decrease position at the current market price\\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\\n MarketDecrease,\\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n LimitDecrease,\\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopLossDecrease,\\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\\n Liquidation,\\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\\n StopIncrease\\n }\\n\\n // to help further differentiate orders\\n enum SecondaryOrderType {\\n None,\\n Adl\\n }\\n\\n enum DecreasePositionSwapType {\\n NoSwap,\\n SwapPnlTokenToCollateralToken,\\n SwapCollateralTokenToPnlToken\\n }\\n\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n // @param _dataList a list of bytes32 values that can be used for additional data\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n bytes32[] _dataList;\\n }\\n\\n // @param account the account of the order\\n // @param receiver the receiver for any token transfers\\n // this field is meant to allow the output of an order to be\\n // received by an address that is different from the creator of the\\n // order whether this is for swaps or whether the account is the owner\\n // of a position\\n // for funding fees and claimable collateral, the funds are still\\n // credited to the owner of the position indicated by order.account\\n // @param callbackContract the contract to call for callbacks\\n // @param uiFeeReceiver the ui fee receiver\\n // @param market the trading market\\n // @param initialCollateralToken for increase orders, initialCollateralToken\\n // is the token sent in by the user, the token will be swapped through the\\n // specified swapPath, before being deposited into the position as collateral\\n // for decrease orders, initialCollateralToken is the collateral token of the position\\n // withdrawn collateral from the decrease of the position will be swapped\\n // through the specified swapPath\\n // for swaps, initialCollateralToken is the initial token sent for the swap\\n // @param swapPath an array of market addresses to swap through\\n struct Addresses {\\n address account;\\n address receiver;\\n address cancellationReceiver;\\n address callbackContract;\\n address uiFeeReceiver;\\n address market;\\n address initialCollateralToken;\\n address[] swapPath;\\n }\\n\\n // @param sizeDeltaUsd the requested change in position size\\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\\n // is the amount of the initialCollateralToken sent in by the user\\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\\n // collateralToken to withdraw\\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\\n // in for the swap\\n // @param orderType the order type\\n // @param triggerPrice the trigger price for non-market orders\\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\\n // @param executionFee the execution fee for keepers\\n // @param callbackGasLimit the gas limit for the callbackContract\\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\\n // note that for decrease orders, multiple tokens could be received, for this reason, the\\n // minOutputAmount value is treated as a USD value for validation in decrease orders\\n // @param srcChainId the source chain id\\n struct Numbers {\\n OrderType orderType;\\n DecreasePositionSwapType decreasePositionSwapType;\\n uint256 sizeDeltaUsd;\\n uint256 initialCollateralDeltaAmount;\\n uint256 triggerPrice;\\n uint256 acceptablePrice;\\n uint256 executionFee;\\n uint256 callbackGasLimit;\\n uint256 minOutputAmount;\\n uint256 updatedAtTime;\\n uint256 validFromTime;\\n uint256 srcChainId;\\n }\\n\\n // @param isLong whether the order is for a long or short\\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\\n // transferring to the user\\n // @param isFrozen whether the order is frozen\\n struct Flags {\\n bool isLong;\\n bool shouldUnwrapNativeToken;\\n bool isFrozen;\\n bool autoCancel;\\n }\\n\\n // @dev the order account\\n // @param props Props\\n // @return the order account\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n // @dev set the order account\\n // @param props Props\\n // @param value the value to set to\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n // @dev the order receiver\\n // @param props Props\\n // @return the order receiver\\n function receiver(Props memory props) internal pure returns (address) {\\n return props.addresses.receiver;\\n }\\n\\n // @dev set the order receiver\\n // @param props Props\\n // @param value the value to set to\\n function setReceiver(Props memory props, address value) internal pure {\\n props.addresses.receiver = value;\\n }\\n\\n function cancellationReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.cancellationReceiver;\\n }\\n\\n function setCancellationReceiver(Props memory props, address value) internal pure {\\n props.addresses.cancellationReceiver = value;\\n }\\n\\n // @dev the order callbackContract\\n // @param props Props\\n // @return the order callbackContract\\n function callbackContract(Props memory props) internal pure returns (address) {\\n return props.addresses.callbackContract;\\n }\\n\\n // @dev set the order callbackContract\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackContract(Props memory props, address value) internal pure {\\n props.addresses.callbackContract = value;\\n }\\n\\n // @dev the order market\\n // @param props Props\\n // @return the order market\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n // @dev set the order market\\n // @param props Props\\n // @param value the value to set to\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n // @dev the order initialCollateralToken\\n // @param props Props\\n // @return the order initialCollateralToken\\n function initialCollateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.initialCollateralToken;\\n }\\n\\n // @dev set the order initialCollateralToken\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.initialCollateralToken = value;\\n }\\n\\n // @dev the order uiFeeReceiver\\n // @param props Props\\n // @return the order uiFeeReceiver\\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\\n return props.addresses.uiFeeReceiver;\\n }\\n\\n // @dev set the order uiFeeReceiver\\n // @param props Props\\n // @param value the value to set to\\n function setUiFeeReceiver(Props memory props, address value) internal pure {\\n props.addresses.uiFeeReceiver = value;\\n }\\n\\n // @dev the order swapPath\\n // @param props Props\\n // @return the order swapPath\\n function swapPath(Props memory props) internal pure returns (address[] memory) {\\n return props.addresses.swapPath;\\n }\\n\\n // @dev set the order swapPath\\n // @param props Props\\n // @param value the value to set to\\n function setSwapPath(Props memory props, address[] memory value) internal pure {\\n props.addresses.swapPath = value;\\n }\\n\\n // @dev the order type\\n // @param props Props\\n // @return the order type\\n function orderType(Props memory props) internal pure returns (OrderType) {\\n return props.numbers.orderType;\\n }\\n\\n // @dev set the order type\\n // @param props Props\\n // @param value the value to set to\\n function setOrderType(Props memory props, OrderType value) internal pure {\\n props.numbers.orderType = value;\\n }\\n\\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\\n return props.numbers.decreasePositionSwapType;\\n }\\n\\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\\n props.numbers.decreasePositionSwapType = value;\\n }\\n\\n // @dev the order sizeDeltaUsd\\n // @param props Props\\n // @return the order sizeDeltaUsd\\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeDeltaUsd;\\n }\\n\\n // @dev set the order sizeDeltaUsd\\n // @param props Props\\n // @param value the value to set to\\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeDeltaUsd = value;\\n }\\n\\n // @dev the order initialCollateralDeltaAmount\\n // @param props Props\\n // @return the order initialCollateralDeltaAmount\\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.initialCollateralDeltaAmount;\\n }\\n\\n // @dev set the order initialCollateralDeltaAmount\\n // @param props Props\\n // @param value the value to set to\\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.initialCollateralDeltaAmount = value;\\n }\\n\\n // @dev the order triggerPrice\\n // @param props Props\\n // @return the order triggerPrice\\n function triggerPrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.triggerPrice;\\n }\\n\\n // @dev set the order triggerPrice\\n // @param props Props\\n // @param value the value to set to\\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\\n props.numbers.triggerPrice = value;\\n }\\n\\n // @dev the order acceptablePrice\\n // @param props Props\\n // @return the order acceptablePrice\\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\\n return props.numbers.acceptablePrice;\\n }\\n\\n // @dev set the order acceptablePrice\\n // @param props Props\\n // @param value the value to set to\\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\\n props.numbers.acceptablePrice = value;\\n }\\n\\n // @dev set the order executionFee\\n // @param props Props\\n // @param value the value to set to\\n function setExecutionFee(Props memory props, uint256 value) internal pure {\\n props.numbers.executionFee = value;\\n }\\n\\n // @dev the order executionFee\\n // @param props Props\\n // @return the order executionFee\\n function executionFee(Props memory props) internal pure returns (uint256) {\\n return props.numbers.executionFee;\\n }\\n\\n // @dev the order callbackGasLimit\\n // @param props Props\\n // @return the order callbackGasLimit\\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\\n return props.numbers.callbackGasLimit;\\n }\\n\\n // @dev set the order callbackGasLimit\\n // @param props Props\\n // @param value the value to set to\\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\\n props.numbers.callbackGasLimit = value;\\n }\\n\\n // @dev the order minOutputAmount\\n // @param props Props\\n // @return the order minOutputAmount\\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.minOutputAmount;\\n }\\n\\n // @dev set the order minOutputAmount\\n // @param props Props\\n // @param value the value to set to\\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.minOutputAmount = value;\\n }\\n\\n // @dev the order updatedAtTime\\n // @param props Props\\n // @return the order updatedAtTime\\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.updatedAtTime;\\n }\\n\\n // @dev set the order updatedAtTime\\n // @param props Props\\n // @param value the value to set to\\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.updatedAtTime = value;\\n }\\n\\n function validFromTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.validFromTime;\\n }\\n function setValidFromTime(Props memory props, uint256 value) internal pure {\\n props.numbers.validFromTime = value;\\n }\\n\\n function srcChainId(Props memory props) internal pure returns (uint256) {\\n return props.numbers.srcChainId;\\n }\\n function setSrcChainId(Props memory props, uint256 value) internal pure {\\n props.numbers.srcChainId = value;\\n }\\n\\n // @dev whether the order is for a long or short\\n // @param props Props\\n // @return whether the order is for a long or short\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n // @dev set whether the order is for a long or short\\n // @param props Props\\n // @param value the value to set to\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev whether to unwrap the native token before transfers to the user\\n // @param props Props\\n // @return whether to unwrap the native token before transfers to the user\\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\\n return props.flags.shouldUnwrapNativeToken;\\n }\\n\\n // @dev set whether the native token should be unwrapped before being\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\\n props.flags.shouldUnwrapNativeToken = value;\\n }\\n\\n // @dev whether the order is frozen\\n // @param props Props\\n // @return whether the order is frozen\\n function isFrozen(Props memory props) internal pure returns (bool) {\\n return props.flags.isFrozen;\\n }\\n\\n // @dev set whether the order is frozen\\n // transferred to the receiver\\n // @param props Props\\n // @param value the value to set to\\n function setIsFrozen(Props memory props, bool value) internal pure {\\n props.flags.isFrozen = value;\\n }\\n\\n function autoCancel(Props memory props) internal pure returns (bool) {\\n return props.flags.autoCancel;\\n }\\n\\n function setAutoCancel(Props memory props, bool value) internal pure {\\n props.flags.autoCancel = value;\\n }\\n\\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\\n return props._dataList;\\n }\\n\\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\\n props._dataList = value;\\n }\\n\\n // @param props Props\\n function touch(Props memory props) internal view {\\n props.setUpdatedAtTime(Chain.currentTimestamp());\\n }\\n\\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopIncrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a market order\\n // @param orderType the order type\\n // @return whether an orderType is a market order\\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\\n // a liquidation order is not considered as a market order\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.MarketDecrease;\\n }\\n\\n // @dev check if an orderType is a swap order\\n // @param orderType the order type\\n // @return whether an orderType is a swap order\\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketSwap ||\\n _orderType == OrderType.LimitSwap;\\n }\\n\\n // @dev check if an orderType is a position order\\n // @param orderType the order type\\n // @return whether an orderType is a position order\\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\\n }\\n\\n // @dev check if an orderType is an increase order\\n // @param orderType the order type\\n // @return whether an orderType is an increase order\\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketIncrease ||\\n _orderType == OrderType.LimitIncrease ||\\n _orderType == OrderType.StopIncrease;\\n }\\n\\n // @dev check if an orderType is a decrease order\\n // @param orderType the order type\\n // @return whether an orderType is a decrease order\\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.MarketDecrease ||\\n _orderType == OrderType.LimitDecrease ||\\n _orderType == OrderType.StopLossDecrease ||\\n _orderType == OrderType.Liquidation;\\n }\\n\\n // @dev check if an orderType is a liquidation order\\n // @param orderType the order type\\n // @return whether an orderType is a liquidation order\\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\\n return _orderType == OrderType.Liquidation;\\n }\\n}\\n\",\"keccak256\":\"0x8b2b69bd354576aab5a08c807c7561863d60bac899eec01268d92536a562bc63\",\"license\":\"BUSL-1.1\"},\"contracts/order/OrderVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../bank/StrictBank.sol\\\";\\n\\n// @title OrderVault\\n// @dev Vault for orders\\ncontract OrderVault is StrictBank {\\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\\n}\\n\",\"keccak256\":\"0x5c4378e51db582baa867cf83627f8d567a5724f9c52d684c3db31535424fa4a2\",\"license\":\"BUSL-1.1\"},\"contracts/position/Position.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Position\\n// @dev Stuct for positions\\n//\\n// borrowing fees for position require only a borrowingFactor to track\\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\\n// a position would be opened with borrowingFactor as 10020%\\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\\n// owe 5% of the position size as borrowing fees\\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\\n// collateral and transferred into the LP pool\\n//\\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\\n// based on the fiat value of the position sizes\\n//\\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\\n// only owe 0.05 longToken ($200)\\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\\n// to be deducted and to be paid out need to be tracked instead\\n//\\n// for funding fees, there are four values to consider:\\n// 1. long positions with market.longToken as collateral\\n// 2. long positions with market.shortToken as collateral\\n// 3. short positions with market.longToken as collateral\\n// 4. short positions with market.shortToken as collateral\\nlibrary Position {\\n // @dev there is a limit on the number of fields a struct can have when being passed\\n // or returned as a memory variable which can cause \\\"Stack too deep\\\" errors\\n // use sub-structs to avoid this issue\\n // @param addresses address values\\n // @param numbers number values\\n // @param flags boolean values\\n struct Props {\\n Addresses addresses;\\n Numbers numbers;\\n Flags flags;\\n }\\n\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n struct Addresses {\\n address account;\\n address market;\\n address collateralToken;\\n }\\n\\n // @param sizeInUsd the position's size in USD\\n // @param sizeInTokens the position's size in tokens\\n // @param collateralAmount the amount of collateralToken for collateral\\n // @param pendingImpactAmount the amount of pending impact for the position\\n // @param borrowingFactor the position's borrowing factor\\n // @param fundingFeeAmountPerSize the position's funding fee per size\\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.longToken\\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\\n // for the market.shortToken\\n // @param increasedAtTime the time at which this position was increased\\n // @param decreasedAtTime the time at which this position was decreased\\n struct Numbers {\\n uint256 sizeInUsd;\\n uint256 sizeInTokens;\\n uint256 collateralAmount;\\n int256 pendingImpactAmount;\\n uint256 borrowingFactor;\\n uint256 fundingFeeAmountPerSize;\\n uint256 longTokenClaimableFundingAmountPerSize;\\n uint256 shortTokenClaimableFundingAmountPerSize;\\n uint256 increasedAtTime;\\n uint256 decreasedAtTime;\\n }\\n\\n // @param isLong whether the position is a long or short\\n struct Flags {\\n bool isLong;\\n }\\n\\n function account(Props memory props) internal pure returns (address) {\\n return props.addresses.account;\\n }\\n\\n function setAccount(Props memory props, address value) internal pure {\\n props.addresses.account = value;\\n }\\n\\n function market(Props memory props) internal pure returns (address) {\\n return props.addresses.market;\\n }\\n\\n function setMarket(Props memory props, address value) internal pure {\\n props.addresses.market = value;\\n }\\n\\n function collateralToken(Props memory props) internal pure returns (address) {\\n return props.addresses.collateralToken;\\n }\\n\\n function setCollateralToken(Props memory props, address value) internal pure {\\n props.addresses.collateralToken = value;\\n }\\n\\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInUsd;\\n }\\n\\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInUsd = value;\\n }\\n\\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\\n return props.numbers.sizeInTokens;\\n }\\n\\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\\n props.numbers.sizeInTokens = value;\\n }\\n\\n function collateralAmount(Props memory props) internal pure returns (uint256) {\\n return props.numbers.collateralAmount;\\n }\\n\\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\\n props.numbers.collateralAmount = value;\\n }\\n\\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\\n return props.numbers.pendingImpactAmount;\\n }\\n\\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\\n props.numbers.pendingImpactAmount = value;\\n }\\n\\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\\n return props.numbers.borrowingFactor;\\n }\\n\\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\\n props.numbers.borrowingFactor = value;\\n }\\n\\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.fundingFeeAmountPerSize;\\n }\\n\\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.fundingFeeAmountPerSize = value;\\n }\\n\\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.longTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\\n }\\n\\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\\n }\\n\\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.increasedAtTime;\\n }\\n\\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.increasedAtTime = value;\\n }\\n\\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\\n return props.numbers.decreasedAtTime;\\n }\\n\\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\\n props.numbers.decreasedAtTime = value;\\n }\\n\\n function isLong(Props memory props) internal pure returns (bool) {\\n return props.flags.isLong;\\n }\\n\\n function setIsLong(Props memory props, bool value) internal pure {\\n props.flags.isLong = value;\\n }\\n\\n // @dev get the key for a position\\n // @param account the position's account\\n // @param market the position's market\\n // @param collateralToken the position's collateralToken\\n // @param isLong whether the position is long or short\\n // @return the position key\\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\\n\\n return _key;\\n }\\n}\\n\",\"keccak256\":\"0xfc97bd5e003b8c51eb0ba1d09cbeca8212a4419b4726cdbe669c8acd4a6aaa20\",\"license\":\"BUSL-1.1\"},\"contracts/position/PositionUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\nimport \\\"./Position.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../pricing/PositionPricingUtils.sol\\\";\\nimport \\\"../order/BaseOrderUtils.sol\\\";\\n\\n// @title PositionUtils\\n// @dev Library for position functions\\nlibrary PositionUtils {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Price for Price.Props;\\n using Position for Position.Props;\\n using Order for Order.Props;\\n\\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\\n // to avoid stack too deep errors\\n //\\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\\n // @param market the values of the trading market\\n // @param order the decrease position order\\n // @param orderKey the key of the order\\n // @param position the order's position\\n // @param positionKey the key of the order's position\\n struct UpdatePositionParams {\\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\\n Market.Props market;\\n Order.Props order;\\n bytes32 orderKey;\\n Position.Props position;\\n bytes32 positionKey;\\n Order.SecondaryOrderType secondaryOrderType;\\n }\\n\\n // @param dataStore DataStore\\n // @param eventEmitter EventEmitter\\n // @param oracle Oracle\\n // @param referralStorage IReferralStorage\\n struct UpdatePositionParamsContracts {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n ISwapHandler swapHandler;\\n IReferralStorage referralStorage;\\n }\\n\\n struct WillPositionCollateralBeSufficientValues {\\n uint256 positionSizeInUsd;\\n uint256 positionCollateralAmount;\\n int256 realizedPnlUsd;\\n int256 openInterestDelta;\\n }\\n\\n struct DecreasePositionCollateralValuesOutput {\\n address outputToken;\\n uint256 outputAmount;\\n address secondaryOutputToken;\\n uint256 secondaryOutputAmount;\\n }\\n\\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\\n // @param executionPrice the order execution price\\n // @param remainingCollateralAmount the remaining collateral amount of the position\\n // @param positionPnlUsd the pnl of the position in USD\\n // @param sizeDeltaInTokens the change in position size in tokens\\n // @param priceImpactAmount the price impact in tokens\\n // @param priceImpactDiffUsd the price impact difference in USD\\n // @param pendingCollateralDeduction the pending collateral deduction\\n // @param output DecreasePositionCollateralValuesOutput\\n struct DecreasePositionCollateralValues {\\n uint256 executionPrice;\\n uint256 remainingCollateralAmount;\\n int256 basePnlUsd;\\n int256 uncappedBasePnlUsd;\\n uint256 sizeDeltaInTokens;\\n int256 priceImpactUsd;\\n int256 proportionalPendingImpactAmount;\\n int256 proportionalPendingImpactUsd;\\n uint256 priceImpactDiffUsd;\\n int256 totalImpactUsd;\\n DecreasePositionCollateralValuesOutput output;\\n }\\n\\n // @dev DecreasePositionCache struct used in decreasePosition to\\n // avoid stack too deep errors\\n // @param prices the prices of the tokens in the market\\n // @param pnlToken the token that the pnl for the user is in, for long positions\\n // this is the market.longToken, for short positions this is the market.shortToken\\n // @param pnlTokenPrice the price of the pnlToken\\n // @param initialCollateralAmount the initial collateral amount\\n // @param nextPositionSizeInUsd the new position size in USD\\n // @param nextPositionBorrowingFactor the new position borrowing factor\\n struct DecreasePositionCache {\\n MarketUtils.MarketPrices prices;\\n int256 estimatedPositionPnlUsd;\\n int256 estimatedRealizedPnlUsd;\\n int256 estimatedRemainingPnlUsd;\\n address pnlToken;\\n Price.Props pnlTokenPrice;\\n Price.Props collateralTokenPrice;\\n uint256 initialCollateralAmount;\\n uint256 nextPositionSizeInUsd;\\n uint256 nextPositionBorrowingFactor;\\n int256 minCollateralUsd;\\n }\\n\\n\\n struct GetPositionPnlUsdCache {\\n int256 positionValue;\\n int256 totalPositionPnl;\\n int256 uncappedTotalPositionPnl;\\n address pnlToken;\\n uint256 poolTokenAmount;\\n uint256 poolTokenPrice;\\n uint256 poolTokenUsd;\\n int256 poolPnl;\\n int256 cappedPoolPnl;\\n uint256 sizeDeltaInTokens;\\n int256 positionPnlUsd;\\n int256 uncappedPositionPnlUsd;\\n }\\n\\n struct IsPositionLiquidatableInfo {\\n int256 remainingCollateralUsd;\\n int256 minCollateralUsd;\\n int256 minCollateralUsdForLeverage;\\n }\\n\\n struct IsPositionLiquidatableCache {\\n int256 positionPnlUsd;\\n uint256 minCollateralFactor;\\n Price.Props collateralTokenPrice;\\n uint256 collateralUsd;\\n int256 usdDeltaForPriceImpact;\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n }\\n\\n struct GetExecutionPriceForIncreaseCache {\\n int256 priceImpactUsd;\\n int256 priceImpactAmount;\\n uint256 baseSizeDeltaInTokens;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n struct GetExecutionPriceForDecreaseCache {\\n int256 priceImpactUsd;\\n bool balanceWasImproved;\\n uint256 executionPrice;\\n }\\n\\n // @dev get the position pnl in USD\\n //\\n // for long positions, pnl is calculated as:\\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\\n // if position.sizeInTokens is larger for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // for short positions, pnl is calculated as:\\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\\n // if position.sizeInTokens is smaller for long positions, the position will have\\n // larger profits and smaller losses for the same changes in token price\\n //\\n // @param position the position values\\n // @param sizeDeltaUsd the change in position size\\n // @param indexTokenPrice the price of the index token\\n //\\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\\n function getPositionPnlUsd(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n Position.Props memory position,\\n uint256 sizeDeltaUsd\\n ) public view returns (int256, int256, uint256) {\\n GetPositionPnlUsdCache memory cache;\\n\\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\\n\\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\\n\\n if (cache.totalPositionPnl > 0) {\\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\\n cache.poolPnl = MarketUtils.getPnl(\\n dataStore,\\n market,\\n prices.indexTokenPrice,\\n position.isLong(),\\n true\\n );\\n\\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\\n dataStore,\\n market.marketToken,\\n position.isLong(),\\n cache.poolPnl,\\n cache.poolTokenUsd,\\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\\n );\\n\\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\\n }\\n }\\n\\n if (position.sizeInUsd() == sizeDeltaUsd) {\\n cache.sizeDeltaInTokens = position.sizeInTokens();\\n } else {\\n if (position.isLong()) {\\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\\n } else {\\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\\n }\\n }\\n\\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\\n\\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\\n }\\n\\n // @dev validate that a position is not empty\\n // @param position the position values\\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\\n revert Errors.EmptyPosition();\\n }\\n }\\n\\n // @dev check if a position is valid\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param market the market values\\n // @param prices the prices of the tokens in the market\\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\\n // validation is skipped for decrease position to prevent reverts in case the order size\\n // is just slightly smaller than the position size\\n // in decrease position, the remaining collateral is estimated at the start, and the order\\n // size is updated to match the position size if the remaining collateral will be less than\\n // the min collateral usd\\n // since this is an estimate, there may be edge cases where there is a small remaining position size\\n // and small amount of collateral remaining\\n // validation is skipped for this case as it is preferred for the order to be executed\\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\\n // keepers\\n function validatePosition(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinPositionSize,\\n bool shouldValidateMinCollateralUsd\\n ) public view {\\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\\n }\\n\\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\\n\\n if (shouldValidateMinPositionSize) {\\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\\n if (position.sizeInUsd() < minPositionSizeUsd) {\\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\\n }\\n }\\n\\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\\n dataStore,\\n referralStorage,\\n position,\\n market,\\n prices,\\n shouldValidateMinCollateralUsd,\\n false // forLiquidation\\n );\\n\\n if (isLiquidatable) {\\n revert Errors.LiquidatablePosition(\\n reason,\\n info.remainingCollateralUsd,\\n info.minCollateralUsd,\\n info.minCollateralUsdForLeverage\\n );\\n }\\n }\\n\\n function isPositionLiquidatable(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Position.Props memory position,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n bool shouldValidateMinCollateralUsd,\\n bool forLiquidation\\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\\n IsPositionLiquidatableCache memory cache;\\n IsPositionLiquidatableInfo memory info;\\n\\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\\n dataStore,\\n market,\\n prices,\\n position,\\n position.sizeInUsd()\\n );\\n\\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n position.collateralToken(),\\n market,\\n prices\\n );\\n\\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\\n\\n // calculate the usdDeltaForPriceImpact for fully closing the position\\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n dataStore,\\n market,\\n cache.usdDeltaForPriceImpact,\\n position.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n dataStore,\\n market.marketToken,\\n cache.priceImpactUsd,\\n position.sizeInUsd()\\n );\\n\\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\\n\\n // even if there is a large positive price impact, positions that would be liquidated\\n // if the positive price impact is reduced should not be allowed to be created\\n // as they would be easily liquidated if the price impact changes\\n // cap the priceImpactUsd to zero to prevent these positions from being created\\n if (cache.priceImpactUsd >= 0) {\\n cache.priceImpactUsd = 0;\\n } else {\\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\\n dataStore,\\n market.marketToken\\n );\\n\\n // if there is a large build up of open interest and a sudden large price movement\\n // it may result in a large imbalance between longs and shorts\\n // this could result in very large price impact temporarily\\n // cap the max negative price impact to prevent cascading liquidations\\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\\n }\\n }\\n\\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\\n dataStore, // dataStore\\n referralStorage, // referralStorage\\n position, // position\\n cache.collateralTokenPrice, //collateralTokenPrice\\n cache.balanceWasImproved, // balanceWasImproved\\n market.longToken, // longToken\\n market.shortToken, // shortToken\\n position.sizeInUsd(), // sizeDeltaUsd\\n address(0), // uiFeeReceiver\\n\\n // should not account for liquidation fees to determine if position should be liquidated\\n false // isLiquidation\\n );\\n\\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\\n\\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\\n // using collateralTokenPrice.min\\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\\n\\n // the position's pnl is counted as collateral for the liquidation check\\n // as a position in profit should not be liquidated if the pnl is sufficient\\n // to cover the position's fees\\n info.remainingCollateralUsd =\\n cache.collateralUsd.toInt256()\\n + cache.positionPnlUsd\\n + cache.priceImpactUsd\\n - collateralCostUsd.toInt256();\\n\\n if (forLiquidation) {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\\n } else {\\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n }\\n\\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\\n // this validation includes the position fee to be paid when closing the position\\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\\n\\n if (shouldValidateMinCollateralUsd) {\\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\\n return (true, \\\"min collateral\\\", info);\\n }\\n }\\n\\n if (info.remainingCollateralUsd <= 0) {\\n return (true, \\\"< 0\\\", info);\\n }\\n\\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\\n return (true, \\\"min collateral for leverage\\\", info);\\n }\\n\\n return (false, \\\"\\\", info);\\n }\\n\\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\\n // this is because this validation is meant to guard against a specific scenario of price impact\\n // gaming\\n //\\n // price impact could be gamed by opening high leverage positions, if the price impact\\n // that should be charged is higher than the amount of collateral in the position\\n // then a user could pay less price impact than what is required, and there is a risk that\\n // price manipulation could be profitable if the price impact cost is less than it should be\\n //\\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\\n // since the funding and borrowing fees would still add up for the user's cost\\n //\\n // another possibility would be if a user opens a large amount of both long and short positions, and\\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\\n // since some time would be required for the funding fees to accumulate\\n //\\n // fees and price impact are validated in the validatePosition check\\n function willPositionCollateralBeSufficient(\\n DataStore dataStore,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices,\\n address collateralToken,\\n bool isLong,\\n WillPositionCollateralBeSufficientValues memory values\\n ) public view returns (bool, int256) {\\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\\n collateralToken,\\n market,\\n prices\\n );\\n\\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\\n\\n // deduct realized pnl if it is negative since this would be paid from\\n // the position's collateral\\n if (values.realizedPnlUsd < 0) {\\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\\n }\\n\\n if (remainingCollateralUsd < 0) {\\n return (false, remainingCollateralUsd);\\n }\\n\\n // the min collateral factor will increase as the open interest for a market increases\\n // this may lead to previously created limit increase orders not being executable\\n //\\n // the position's pnl is not factored into the remainingCollateralUsd value, since\\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\\n // it may be useful to factor in a negative pnl for this check, this can be added if required\\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\\n dataStore,\\n market,\\n values.openInterestDelta,\\n isLong\\n );\\n\\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\\n // use the minCollateralFactor for the market if it is larger\\n if (minCollateralFactorForMarket > minCollateralFactor) {\\n minCollateralFactor = minCollateralFactorForMarket;\\n }\\n\\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\\n\\n return (willBeSufficient, remainingCollateralUsd);\\n }\\n\\n function updateFundingAndBorrowingState(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n Market.Props memory market,\\n MarketUtils.MarketPrices memory prices\\n ) external {\\n // update the funding amount per size for the market\\n MarketUtils.updateFundingState(\\n dataStore,\\n eventEmitter,\\n market,\\n prices\\n );\\n\\n // update the cumulative borrowing factor for longs\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n true // isLong\\n );\\n\\n // update the cumulative borrowing factor for shorts\\n MarketUtils.updateCumulativeBorrowingFactor(\\n dataStore,\\n eventEmitter,\\n market,\\n prices,\\n false // isLong\\n );\\n }\\n\\n function updateTotalBorrowing(\\n PositionUtils.UpdatePositionParams memory params,\\n uint256 nextPositionSizeInUsd,\\n uint256 nextPositionBorrowingFactor\\n ) internal {\\n MarketUtils.updateTotalBorrowing(\\n params.contracts.dataStore, // dataStore\\n params.market.marketToken, // market\\n params.position.isLong(), // isLong\\n params.position.sizeInUsd(), // prevPositionSizeInUsd\\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\\n nextPositionSizeInUsd, // nextPositionSizeInUsd\\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\\n );\\n }\\n\\n // the order.receiver is meant to allow the output of an order to be\\n // received by an address that is different from the position.account\\n // address\\n // for funding fees, the funds are still credited to the owner\\n // of the position indicated by order.account\\n function incrementClaimableFundingAmount(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n // if the position has negative funding fees, distribute it to allow it to be claimable\\n if (fees.funding.claimableLongTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.longToken,\\n params.order.account(),\\n fees.funding.claimableLongTokenAmount\\n );\\n }\\n\\n if (fees.funding.claimableShortTokenAmount > 0) {\\n MarketUtils.incrementClaimableFundingAmount(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market.marketToken,\\n params.market.shortToken,\\n params.order.account(),\\n fees.funding.claimableShortTokenAmount\\n );\\n }\\n }\\n\\n function updateOpenInterest(\\n PositionUtils.UpdatePositionParams memory params,\\n int256 sizeDeltaUsd,\\n int256 sizeDeltaInTokens\\n ) internal {\\n if (sizeDeltaUsd != 0) {\\n MarketUtils.applyDeltaToOpenInterest(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.market,\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaUsd\\n );\\n\\n MarketUtils.applyDeltaToOpenInterestInTokens(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong(),\\n sizeDeltaInTokens\\n );\\n }\\n }\\n\\n function handleReferral(\\n PositionUtils.UpdatePositionParams memory params,\\n PositionPricingUtils.PositionFees memory fees\\n ) internal {\\n ReferralUtils.incrementAffiliateReward(\\n params.contracts.dataStore,\\n params.contracts.eventEmitter,\\n params.position.market(),\\n params.position.collateralToken(),\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardAmount\\n );\\n }\\n\\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\\n function getExecutionPriceForIncrease(\\n UpdatePositionParams memory params,\\n MarketUtils.MarketPrices memory prices\\n ) external view returns (int256, int256, uint256, uint256, bool) {\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (params.order.sizeDeltaUsd() == 0) {\\n // increase order:\\n // - long: use the larger price\\n // - short: use the smaller price\\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForIncreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n params.order.sizeDeltaUsd().toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n // note that the positive priceImpactUsd is not capped by the position impact pool here\\n // this is to prevent cases where for new markets, user A opens a position with negative\\n // price impact and user B does not have any incentive to open a position to balance the pool\\n // because the price impact pool is empty until user A closes\\n // the positive price impact will still be capped during position decrease when the positive\\n // price impact is actually paid out\\n //\\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\\n // uncertain when the impact pool state would be when the position is actually\\n // closed and the impact is to be realized\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n // for long positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n // for short positions\\n //\\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\\n // the priceImpactAmount should be minimized\\n //\\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\\n // the priceImpactAmount should be maximized\\n\\n if (cache.priceImpactUsd > 0) {\\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\\n } else {\\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\\n }\\n\\n if (params.position.isLong()) {\\n // round the number of tokens for long positions down\\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\\n } else {\\n // round the number of tokens for short positions up\\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\\n }\\n\\n int256 sizeDeltaInTokens;\\n if (params.position.isLong()) {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\\n } else {\\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\\n }\\n\\n if (sizeDeltaInTokens < 0) {\\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\\n }\\n\\n // using increase of long positions as an example\\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\\n // priceImpactAmount = -1000 / 2000 = -0.5\\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\\n // executionPrice = 5000 / 2 = $2500\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\\n params.order.sizeDeltaUsd(),\\n sizeDeltaInTokens.toUint256(),\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\\n }\\n\\n // returns priceImpactUsd, executionPrice, balanceWasImproved\\n function getExecutionPriceForDecrease(\\n UpdatePositionParams memory params,\\n Price.Props memory indexTokenPrice\\n ) external view returns (int256, uint256, bool) {\\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\\n\\n // note that the executionPrice is not validated against the order.acceptablePrice value\\n // if the sizeDeltaUsd is zero\\n // for limit orders the order.triggerPrice should still have been validated\\n if (sizeDeltaUsd == 0) {\\n // decrease order:\\n // - long: use the smaller price\\n // - short: use the larger price\\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\\n }\\n\\n GetExecutionPriceForDecreaseCache memory cache;\\n\\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\\n PositionPricingUtils.GetPriceImpactUsdParams(\\n params.contracts.dataStore,\\n params.market,\\n -sizeDeltaUsd.toInt256(),\\n params.order.isLong()\\n )\\n );\\n\\n // cap positive priceImpactUsd based on the max positive position impact factor\\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\\n params.contracts.dataStore,\\n params.market.marketToken,\\n cache.priceImpactUsd,\\n params.order.sizeDeltaUsd()\\n );\\n\\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\\n indexTokenPrice,\\n params.position.sizeInUsd(),\\n params.position.sizeInTokens(),\\n sizeDeltaUsd,\\n cache.priceImpactUsd,\\n params.order.acceptablePrice(),\\n params.position.isLong()\\n );\\n\\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\\n }\\n}\\n\",\"keccak256\":\"0xa7a5a10c9321e7372bc6a8c11da319e6421ed5c0676810a1c8ec30c30f730331\",\"license\":\"BUSL-1.1\"},\"contracts/price/Price.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title Price\\n// @dev Struct for prices\\nlibrary Price {\\n // @param min the min price\\n // @param max the max price\\n struct Props {\\n uint256 min;\\n uint256 max;\\n }\\n\\n // @dev check if a price is empty\\n // @param props Props\\n // @return whether a price is empty\\n function isEmpty(Props memory props) internal pure returns (bool) {\\n return props.min == 0 || props.max == 0;\\n }\\n\\n // @dev get the average of the min and max values\\n // @param props Props\\n // @return the average of the min and max values\\n function midPrice(Props memory props) internal pure returns (uint256) {\\n return (props.max + props.min) / 2;\\n }\\n\\n // @dev pick either the min or max value\\n // @param props Props\\n // @param maximize whether to pick the min or max value\\n // @return either the min or max value\\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\\n return maximize ? props.max : props.min;\\n }\\n\\n // @dev pick the min or max price depending on whether it is for a long or short position\\n // and whether the pending pnl should be maximized or not\\n // @param props Props\\n // @param isLong whether it is for a long or short position\\n // @param maximize whether the pnl should be maximized or not\\n // @return the min or max price\\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\\n // for long positions, pick the larger price to maximize pnl\\n // for short positions, pick the smaller price to maximize pnl\\n if (isLong) {\\n return maximize ? props.max : props.min;\\n }\\n\\n return maximize ? props.min : props.max;\\n }\\n}\\n\",\"keccak256\":\"0x39783950d37d565ee3fbff5023206cfb6993bb49523e7fe37f367393cb54bedd\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/ISwapPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISwapPricingUtils {\\n enum SwapPricingType {\\n Swap,\\n Shift,\\n AtomicWithdrawal,\\n Deposit,\\n Withdrawal,\\n AtomicSwap\\n }\\n}\\n\",\"keccak256\":\"0x8504d26a64dbbc21e250abe890c99b0558879617c44590285f05a62315f1b288\",\"license\":\"MIT\"},\"contracts/pricing/PositionPricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\n\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\nimport \\\"../utils/Calc.sol\\\";\\n\\nimport \\\"./PricingUtils.sol\\\";\\n\\nimport \\\"../referral/IReferralStorage.sol\\\";\\nimport \\\"../referral/ReferralUtils.sol\\\";\\n\\n// @title PositionPricingUtils\\n// @dev Library for position pricing functions\\nlibrary PositionPricingUtils {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using Position for Position.Props;\\n using Price for Price.Props;\\n\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n struct GetPositionFeesParams {\\n DataStore dataStore;\\n IReferralStorage referralStorage;\\n Position.Props position;\\n Price.Props collateralTokenPrice;\\n bool balanceWasImproved;\\n address longToken;\\n address shortToken;\\n uint256 sizeDeltaUsd;\\n address uiFeeReceiver;\\n bool isLiquidation;\\n }\\n\\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\\n // too deep errors\\n // @param dataStore DataStore\\n // @param market the market to check\\n // @param usdDelta the change in position size in USD\\n // @param isLong whether the position is long or short\\n struct GetPriceImpactUsdParams {\\n DataStore dataStore;\\n Market.Props market;\\n int256 usdDelta;\\n bool isLong;\\n }\\n\\n // @dev OpenInterestParams struct to contain open interest values\\n // @param longOpenInterest the amount of long open interest\\n // @param shortOpenInterest the amount of short open interest\\n // @param nextLongOpenInterest the updated amount of long open interest\\n // @param nextShortOpenInterest the updated amount of short open interest\\n struct OpenInterestParams {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n uint256 nextLongOpenInterest;\\n uint256 nextShortOpenInterest;\\n }\\n\\n // @dev PositionFees struct to contain fee values\\n // @param feeReceiverAmount the amount for the fee receiver\\n // @param feeAmountForPool the amount of fees for the pool\\n // @param positionFeeAmountForPool the position fee amount for the pool\\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\\n // @param borrowingFeeAmount the borrowing fee amount\\n // @param totalCostAmount the total cost amount in tokens\\n struct PositionFees {\\n PositionReferralFees referral;\\n PositionProFees pro;\\n PositionFundingFees funding;\\n PositionBorrowingFees borrowing;\\n PositionUiFees ui;\\n PositionLiquidationFees liquidation;\\n Price.Props collateralTokenPrice;\\n uint256 positionFeeFactor;\\n uint256 protocolFeeAmount;\\n uint256 positionFeeReceiverFactor;\\n uint256 feeReceiverAmount;\\n uint256 feeAmountForPool;\\n uint256 positionFeeAmountForPool;\\n uint256 positionFeeAmount;\\n uint256 totalCostAmountExcludingFunding;\\n uint256 totalCostAmount;\\n uint256 totalDiscountAmount;\\n }\\n\\n struct PositionProFees {\\n uint256 traderTier;\\n uint256 traderDiscountFactor;\\n uint256 traderDiscountAmount;\\n }\\n\\n struct PositionLiquidationFees {\\n uint256 liquidationFeeUsd;\\n uint256 liquidationFeeAmount;\\n uint256 liquidationFeeReceiverFactor;\\n uint256 liquidationFeeAmountForFeeReceiver;\\n }\\n\\n // @param affiliate the referral affiliate of the trader\\n // @param traderDiscountAmount the discount amount for the trader\\n // @param affiliateRewardAmount the affiliate reward amount\\n struct PositionReferralFees {\\n bytes32 referralCode;\\n address affiliate;\\n address trader;\\n uint256 totalRebateFactor;\\n uint256 affiliateRewardFactor;\\n uint256 adjustedAffiliateRewardFactor;\\n uint256 traderDiscountFactor;\\n uint256 totalRebateAmount;\\n uint256 traderDiscountAmount;\\n uint256 affiliateRewardAmount;\\n }\\n\\n struct PositionBorrowingFees {\\n uint256 borrowingFeeUsd;\\n uint256 borrowingFeeAmount;\\n uint256 borrowingFeeReceiverFactor;\\n uint256 borrowingFeeAmountForFeeReceiver;\\n }\\n\\n // @param fundingFeeAmount the position's funding fee amount\\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\\n // amount per size for the market\\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\\n // amount per size for the market\\n struct PositionFundingFees {\\n uint256 fundingFeeAmount;\\n uint256 claimableLongTokenAmount;\\n uint256 claimableShortTokenAmount;\\n uint256 latestFundingFeeAmountPerSize;\\n uint256 latestLongTokenClaimableFundingAmountPerSize;\\n uint256 latestShortTokenClaimableFundingAmountPerSize;\\n }\\n\\n struct PositionUiFees {\\n address uiFeeReceiver;\\n uint256 uiFeeReceiverFactor;\\n uint256 uiFeeAmount;\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\\n\\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\\n\\n // the virtual price impact calculation is skipped if the price impact\\n // is positive since the action is helping to balance the pool\\n //\\n // in case two virtual pools are unbalanced in a different direction\\n // e.g. pool0 has more longs than shorts while pool1 has less longs\\n // than shorts\\n // not skipping the virtual price impact calculation would lead to\\n // a negative price impact for any trade on either pools and would\\n // disincentivise the balancing of pools\\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\\n\\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\\n\\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\\n\\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\\n }\\n\\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\\n // @param dataStore DataStore\\n // @param market the trading market\\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\\n\\n // check whether an improvement in balance comes from causing the balance to switch sides\\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\\n\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n if (isSameSideRebalance) {\\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n impactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n } else {\\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\\n\\n return (\\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\\n initialDiffUsd,\\n nextDiffUsd,\\n positiveImpactFactor,\\n negativeImpactFactor,\\n impactExponentFactor\\n ),\\n balanceWasImproved\\n );\\n }\\n }\\n\\n // @dev get the next open interest values\\n // @param params GetPriceImpactUsdParams\\n // @return OpenInterestParams\\n function getNextOpenInterest(\\n GetPriceImpactUsdParams memory params\\n ) internal view returns (OpenInterestParams memory) {\\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n true\\n );\\n\\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\\n params.dataStore,\\n params.market,\\n false\\n );\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestForVirtualInventory(\\n GetPriceImpactUsdParams memory params,\\n int256 virtualInventory\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 longOpenInterest;\\n uint256 shortOpenInterest;\\n\\n // if virtualInventory is more than zero it means that\\n // tokens were virtually sold to the pool, so set shortOpenInterest\\n // to the virtualInventory value\\n // if virtualInventory is less than zero it means that\\n // tokens were virtually bought from the pool, so set longOpenInterest\\n // to the virtualInventory value\\n if (virtualInventory > 0) {\\n shortOpenInterest = virtualInventory.toUint256();\\n } else {\\n longOpenInterest = (-virtualInventory).toUint256();\\n }\\n\\n // the virtual long and short open interest is adjusted by the usdDelta\\n // to prevent an underflow in getNextOpenInterestParams\\n // price impact depends on the change in USD balance, so offsetting both\\n // values equally should not change the price impact calculation\\n if (params.usdDelta < 0) {\\n uint256 offset = (-params.usdDelta).toUint256();\\n longOpenInterest += offset;\\n shortOpenInterest += offset;\\n }\\n\\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\\n }\\n\\n function getNextOpenInterestParams(\\n GetPriceImpactUsdParams memory params,\\n uint256 longOpenInterest,\\n uint256 shortOpenInterest\\n ) internal pure returns (OpenInterestParams memory) {\\n uint256 nextLongOpenInterest = longOpenInterest;\\n uint256 nextShortOpenInterest = shortOpenInterest;\\n\\n if (params.isLong) {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\\n }\\n\\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\\n } else {\\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\\n }\\n\\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\\n }\\n\\n OpenInterestParams memory openInterestParams = OpenInterestParams(\\n longOpenInterest,\\n shortOpenInterest,\\n nextLongOpenInterest,\\n nextShortOpenInterest\\n );\\n\\n return openInterestParams;\\n }\\n\\n // @dev get position fees\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param position the position values\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param longToken the long token of the market\\n // @param shortToken the short token of the market\\n // @param sizeDeltaUsd the change in position size\\n // @return PositionFees\\n function getPositionFees(\\n GetPositionFeesParams memory params\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees = getPositionFeesAfterReferral(\\n params.dataStore,\\n params.referralStorage,\\n params.collateralTokenPrice,\\n params.balanceWasImproved,\\n params.position.account(),\\n params.position.market(),\\n params.sizeDeltaUsd\\n );\\n\\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\\n\\n fees.borrowing = getBorrowingFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n borrowingFeeUsd\\n );\\n\\n if (params.isLiquidation) {\\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\\n }\\n\\n fees.feeAmountForPool =\\n fees.positionFeeAmountForPool +\\n fees.borrowing.borrowingFeeAmount -\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmount -\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.feeReceiverAmount +=\\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\\n\\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.position.collateralToken(),\\n params.position.isLong()\\n );\\n\\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.longToken,\\n params.position.isLong()\\n );\\n\\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\\n params.dataStore,\\n params.position.market(),\\n params.shortToken,\\n params.position.isLong()\\n );\\n\\n fees.funding = getFundingFees(\\n fees.funding,\\n params.position\\n );\\n\\n fees.ui = getUiFees(\\n params.dataStore,\\n params.collateralTokenPrice,\\n params.sizeDeltaUsd,\\n params.uiFeeReceiver\\n );\\n\\n fees.totalCostAmountExcludingFunding =\\n fees.positionFeeAmount\\n + fees.borrowing.borrowingFeeAmount\\n + fees.liquidation.liquidationFeeAmount\\n + fees.ui.uiFeeAmount\\n - fees.totalDiscountAmount;\\n\\n fees.totalCostAmount =\\n fees.totalCostAmountExcludingFunding\\n + fees.funding.fundingFeeAmount;\\n\\n return fees;\\n }\\n\\n function getBorrowingFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 borrowingFeeUsd\\n ) internal view returns (PositionBorrowingFees memory) {\\n PositionBorrowingFees memory borrowingFees;\\n\\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\\n\\n return borrowingFees;\\n }\\n\\n function getFundingFees(\\n PositionFundingFees memory fundingFees,\\n Position.Props memory position\\n ) internal pure returns (PositionFundingFees memory) {\\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestFundingFeeAmountPerSize,\\n position.fundingFeeAmountPerSize(),\\n position.sizeInUsd(),\\n true // roundUpMagnitude\\n );\\n\\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\\n position.longTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\\n position.shortTokenClaimableFundingAmountPerSize(),\\n position.sizeInUsd(),\\n false // roundUpMagnitude\\n );\\n\\n return fundingFees;\\n }\\n\\n function getUiFees(\\n DataStore dataStore,\\n Price.Props memory collateralTokenPrice,\\n uint256 sizeDeltaUsd,\\n address uiFeeReceiver\\n ) internal view returns (PositionUiFees memory) {\\n PositionUiFees memory uiFees;\\n\\n if (uiFeeReceiver == address(0)) {\\n return uiFees;\\n }\\n\\n uiFees.uiFeeReceiver = uiFeeReceiver;\\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\\n\\n return uiFees;\\n }\\n\\n // @dev get position fees after applying referral rebates / discounts\\n // @param dataStore DataStore\\n // @param referralStorage IReferralStorage\\n // @param collateralTokenPrice the price of the position's collateralToken\\n // @param the position's account\\n // @param market the position's market\\n // @param sizeDeltaUsd the change in position size\\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\\n function getPositionFeesAfterReferral(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n Price.Props memory collateralTokenPrice,\\n bool balanceWasImproved,\\n address account,\\n address market,\\n uint256 sizeDeltaUsd\\n ) internal view returns (PositionFees memory) {\\n PositionFees memory fees;\\n\\n fees.collateralTokenPrice = collateralTokenPrice;\\n\\n fees.referral.trader = account;\\n uint256 minAffiliateRewardFactor;\\n (\\n fees.referral.referralCode,\\n fees.referral.affiliate,\\n fees.referral.affiliateRewardFactor,\\n fees.referral.traderDiscountFactor,\\n minAffiliateRewardFactor\\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\\n\\n // note that since it is possible to incur both positive and negative price impact values\\n // and the negative price impact factor may be larger than the positive impact factor\\n // it is possible for the balance to be improved overall but for the price impact to still be negative\\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\\n\\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\\n // the exact criteria and usage of this feature should be decided by the DAO\\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\\n if (fees.pro.traderTier > 0) {\\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\\n\\n if (fees.pro.traderDiscountFactor > 0) {\\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\\n }\\n }\\n\\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\\n // but can not be lower than configured min affiliate reward\\n //\\n // example 1:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\\n // protocol gets 80%\\n //\\n // example 2:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\\n // protocol gets 80%\\n //\\n // example 3:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 77%\\n //\\n // example 4:\\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\\n // protocol gets 70%\\n\\n if (fees.referral.referralCode != bytes32(0)) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\\n // if pro discount is higher than referral discount then affiliate reward should be capped\\n // at max of (min affiliate reward, total referral rebate - pro discount)\\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\\n ? minAffiliateRewardFactor\\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\\n }\\n }\\n\\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\\n }\\n\\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\\n ? fees.pro.traderDiscountAmount\\n : fees.referral.traderDiscountAmount;\\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\\n\\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\\n\\n return fees;\\n }\\n\\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\\n PositionLiquidationFees memory liquidationFees;\\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\\n if (liquidationFeeFactor == 0) {\\n return liquidationFees;\\n }\\n\\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\\n return liquidationFees;\\n }\\n}\\n\",\"keccak256\":\"0xcc13189a45a45dd9e0b415ca0526dfd3fd1f661a5ef8e1c1b6a1f3e5190b1d37\",\"license\":\"BUSL-1.1\"},\"contracts/pricing/PricingUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Calc.sol\\\";\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title PricingUtils\\n// @dev Library for pricing functions\\n//\\n// Price impact is calculated as:\\n//\\n// ```\\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\\n// ```\\n//\\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\\n// difference in the worth of the long tokens and short tokens.\\n//\\n// For example:\\n//\\n// - A pool has 10 long tokens, each long token is worth $5000\\n// - The pool also has 50,000 short tokens, each short token is worth $1\\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\\n// to `0.01 / 50,000`\\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\\n// short tokens\\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\\n// tokens and $50,000 of short tokens\\n// - The change in imbalance would be from $0 to -$50,000\\n// - There would be negative price impact charged on the user's deposit,\\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\\n// - If the user now withdraws 5 long tokens, the balance would change\\n// from -$50,000 to -$25,000, a net change of +$25,000\\n// - There would be a positive price impact rebated to the user in the form of\\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\\n//\\n// For position actions (increase / decrease position), imbalance is calculated\\n// as the difference in the long and short open interest.\\n//\\n// `price impact exponents` and `price impact factors` are configured per market\\n// and can differ for spot and position actions.\\n//\\n// The purpose of the price impact is to help reduce the risk of price manipulation,\\n// since the contracts use an oracle price which would be an average or median price\\n// of multiple reference exchanges. Without a price impact, it may be profitable to\\n// manipulate the prices on reference exchanges while executing orders on the contracts.\\n//\\n// This risk will also be present if the positive and negative price impact values\\n// are similar, for that reason the positive price impact should be set to a low\\n// value in times of volatility or irregular price movements.\\nlibrary PricingUtils {\\n // @dev get the price impact USD if there is no crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForSameSideRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\\n\\n uint256 deltaDiffUsd = Calc.diff(\\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\\n );\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev get the price impact USD if there is a crossover in balance\\n // a crossover in balance is for example if the long open interest is larger\\n // than the short open interest, and a short position is opened such that the\\n // short open interest becomes larger than the long open interest\\n // @param initialDiffUsd the initial difference in USD\\n // @param nextDiffUsd the next difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function getPriceImpactUsdForCrossoverRebalance(\\n uint256 initialDiffUsd,\\n uint256 nextDiffUsd,\\n uint256 positiveImpactFactor,\\n uint256 negativeImpactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (int256) {\\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\\n\\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\\n\\n return priceImpactUsd;\\n }\\n\\n // @dev apply the impact factor calculation to a USD diff value\\n // @param diffUsd the difference in USD\\n // @param impactFactor the impact factor\\n // @param impactExponentFactor the impact exponent factor\\n function applyImpactFactor(\\n uint256 diffUsd,\\n uint256 impactFactor,\\n uint256 impactExponentFactor\\n ) internal pure returns (uint256) {\\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\\n return Precision.applyFactor(exponentValue, impactFactor);\\n }\\n}\\n\",\"keccak256\":\"0x9b20499c3d2c3e7dd9082682f2b511ca1e4ac8f74b90b987e225bc80b039e291\",\"license\":\"BUSL-1.1\"},\"contracts/referral/IReferralStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// @title IReferralStorage\\n// @dev Interface for ReferralStorage\\ninterface IReferralStorage {\\n // @dev get the owner of a referral code\\n // @param _code the referral code\\n // @return the owner of the referral code\\n function codeOwners(bytes32 _code) external view returns (address);\\n // @dev get the referral code of a trader\\n // @param _account the address of the trader\\n // @return the referral code\\n function traderReferralCodes(address _account) external view returns (bytes32);\\n // @dev get the trader discount share for an affiliate\\n // @param _account the address of the affiliate\\n // @return the trader discount share\\n function referrerDiscountShares(address _account) external view returns (uint256);\\n // @dev get the tier level of an affiliate\\n // @param _account the address of the affiliate\\n // @return the tier level of the affiliate\\n function referrerTiers(address _account) external view returns (uint256);\\n // @dev get the referral info for a trader\\n // @param _account the address of the trader\\n // @return (referral code, affiliate)\\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\\n // @dev set the referral code for a trader\\n // @param _account the address of the trader\\n // @param _code the referral code\\n function setTraderReferralCode(address _account, bytes32 _code) external;\\n // @dev set the values for a tier\\n // @param _tierId the tier level\\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\\n // @param _discountShare the share of the totalRebate for traders\\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\\n // @dev set the tier for an affiliate\\n // @param _tierId the tier level\\n function setReferrerTier(address _referrer, uint256 _tierId) external;\\n // @dev set the owner for a referral code\\n // @param _code the referral code\\n // @param _newAccount the new owner\\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\\n\\n // @dev get the tier values for a tier level\\n // @param _tierLevel the tier level\\n // @return (totalRebate, discountShare)\\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\\n}\\n\",\"keccak256\":\"0xb4730e94f2026fc942e8df90d2d94f7b8faade6e919f314f59eb1099c7064693\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralEventUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../event/EventUtils.sol\\\";\\nimport \\\"../utils/Cast.sol\\\";\\n\\nlibrary ReferralEventUtils {\\n using EventUtils for EventUtils.AddressItems;\\n using EventUtils for EventUtils.UintItems;\\n using EventUtils for EventUtils.IntItems;\\n using EventUtils for EventUtils.BoolItems;\\n using EventUtils for EventUtils.Bytes32Items;\\n using EventUtils for EventUtils.BytesItems;\\n using EventUtils for EventUtils.StringItems;\\n\\n function emitAffiliateRewardUpdated(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta,\\n uint256 nextValue,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(3);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n\\n eventData.uintItems.initItems(3);\\n eventData.uintItems.setItem(0, \\\"delta\\\", delta);\\n eventData.uintItems.setItem(1, \\\"nextValue\\\", nextValue);\\n eventData.uintItems.setItem(2, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog2(\\n \\\"AffiliateRewardUpdated\\\",\\n Cast.toBytes32(market),\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n\\n function emitAffiliateRewardClaimed(\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n address receiver,\\n uint256 amount,\\n uint256 nextPoolValue\\n ) external {\\n EventUtils.EventLogData memory eventData;\\n\\n eventData.addressItems.initItems(4);\\n eventData.addressItems.setItem(0, \\\"market\\\", market);\\n eventData.addressItems.setItem(1, \\\"token\\\", token);\\n eventData.addressItems.setItem(2, \\\"affiliate\\\", affiliate);\\n eventData.addressItems.setItem(3, \\\"receiver\\\", receiver);\\n\\n eventData.uintItems.initItems(2);\\n eventData.uintItems.setItem(0, \\\"amount\\\", amount);\\n eventData.uintItems.setItem(1, \\\"nextPoolValue\\\", nextPoolValue);\\n\\n eventEmitter.emitEventLog1(\\n \\\"AffiliateRewardClaimed\\\",\\n Cast.toBytes32(affiliate),\\n eventData\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcbf2a21b4051e6857835cb6e2025695cd9664c8e875be4583a3c642442f2ea71\",\"license\":\"BUSL-1.1\"},\"contracts/referral/ReferralUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\n\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../market/MarketToken.sol\\\";\\nimport \\\"../market/MarketUtils.sol\\\";\\n\\nimport \\\"./IReferralStorage.sol\\\";\\nimport \\\"./ReferralEventUtils.sol\\\";\\n\\nimport \\\"../utils/Precision.sol\\\";\\n\\n// @title ReferralUtils\\n// @dev Library for referral functions\\nlibrary ReferralUtils {\\n // @dev set the referral code for a trader\\n // @param referralStorage The referral storage instance to use.\\n // @param account The account of the trader.\\n // @param referralCode The referral code.\\n function setTraderReferralCode(\\n IReferralStorage referralStorage,\\n address account,\\n bytes32 referralCode\\n ) internal {\\n if (referralCode == bytes32(0)) { return; }\\n if (address(referralStorage) == address(0)) { return; }\\n\\n // skip setting of the referral code if the user already has a referral code\\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\\n\\n referralStorage.setTraderReferralCode(account, referralCode);\\n }\\n\\n // @dev Increments the affiliate's reward balance by the specified delta.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param market The market address.\\n // @param token The token address.\\n // @param affiliate The affiliate's address.\\n // @param trader The trader's address.\\n // @param delta The amount to increment the reward balance by.\\n function incrementAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address affiliate,\\n uint256 delta\\n ) internal {\\n if (delta == 0) { return; }\\n\\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\\n\\n ReferralEventUtils.emitAffiliateRewardUpdated(\\n eventEmitter,\\n market,\\n token,\\n affiliate,\\n delta,\\n nextValue,\\n nextPoolValue\\n );\\n }\\n\\n // @dev Gets the referral information for the specified trader.\\n // @param referralStorage The referral storage instance to use.\\n // @param trader The trader's address.\\n // @return The affiliate's address, the total rebate, and the discount share.\\n function getReferralInfo(\\n DataStore dataStore,\\n IReferralStorage referralStorage,\\n address trader\\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\\n if (address(referralStorage) == address(0)) {\\n return (bytes32(0), address(0), 0, 0, 0);\\n }\\n\\n bytes32 code = referralStorage.traderReferralCodes(trader);\\n address affiliate;\\n uint256 totalRebate;\\n uint256 discountShare;\\n uint256 minAffiliateRewardFactor;\\n\\n if (code != bytes32(0)) {\\n affiliate = referralStorage.codeOwners(code);\\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\\n\\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\\n if (customDiscountShare != 0) {\\n discountShare = customDiscountShare;\\n }\\n }\\n\\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\\n\\n return (\\n code,\\n affiliate,\\n affiliateRewardFactor,\\n traderDiscountFactor,\\n minAffiliateRewardFactor\\n );\\n }\\n\\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\\n // @param dataStore The data store instance to use.\\n // @param eventEmitter The event emitter instance to use.\\n // @param markets An array of market addresses\\n // @param tokens An array of token addresses, corresponding to the given markets\\n // @param receiver The address to which the claimed rewards should be sent\\n // @param account The affiliate's address.\\n function batchClaimAffiliateRewards(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address[] memory markets,\\n address[] memory tokens,\\n address receiver,\\n address account\\n ) external returns (uint256[] memory) {\\n if (markets.length != tokens.length) {\\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\\n }\\n\\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256[] memory claimedAmounts = new uint256[](markets.length);\\n\\n for (uint256 i; i < markets.length; i++) {\\n claimedAmounts[i] = _claimAffiliateReward(\\n dataStore,\\n eventEmitter,\\n markets[i],\\n tokens[i],\\n account,\\n receiver\\n );\\n }\\n\\n return claimedAmounts;\\n }\\n\\n function _claimAffiliateReward(\\n DataStore dataStore,\\n EventEmitter eventEmitter,\\n address market,\\n address token,\\n address account,\\n address receiver\\n ) private returns (uint256) {\\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\\n\\n uint256 rewardAmount = dataStore.getUint(key);\\n dataStore.setUint(key, 0);\\n\\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\\n\\n MarketToken(payable(market)).transferOut(\\n token,\\n receiver,\\n rewardAmount\\n );\\n\\n MarketUtils.validateMarketTokenBalance(dataStore, market);\\n\\n ReferralEventUtils.emitAffiliateRewardClaimed(\\n eventEmitter,\\n market,\\n token,\\n account,\\n receiver,\\n rewardAmount,\\n nextPoolValue\\n );\\n\\n return rewardAmount;\\n }\\n}\\n\",\"keccak256\":\"0xc53867a7ca27d0d14321bb3f0753cdc54a03156d5259867a20e5ea767764fd1a\",\"license\":\"BUSL-1.1\"},\"contracts/role/Role.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Role\\n * @dev Library for role keys\\n */\\nlibrary Role {\\n /**\\n * @dev The ROLE_ADMIN role.\\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\\n */\\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\\\"ROLE_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_ADMIN role.\\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\\n */\\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\\\"TIMELOCK_ADMIN\\\"));\\n\\n /**\\n * @dev The TIMELOCK_MULTISIG role.\\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\\n */\\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\\\"TIMELOCK_MULTISIG\\\"));\\n\\n /**\\n * @dev The CONFIG_KEEPER role.\\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\\n */\\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\\\"CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The LIMITED_CONFIG_KEEPER role.\\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\\n */\\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\\\"LIMITED_CONFIG_KEEPER\\\"));\\n\\n /**\\n * @dev The CONTROLLER role.\\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\\n */\\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\\\"CONTROLLER\\\"));\\n\\n /**\\n * @dev The GOV_TOKEN_CONTROLLER role.\\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\\n */\\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\\\"GOV_TOKEN_CONTROLLER\\\"));\\n\\n /**\\n * @dev The ROUTER_PLUGIN role.\\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\\n */\\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\\\"ROUTER_PLUGIN\\\"));\\n\\n /**\\n * @dev The MARKET_KEEPER role.\\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\\n */\\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\\\"MARKET_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_KEEPER role.\\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\\n */\\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\\\"FEE_KEEPER\\\"));\\n\\n /**\\n * @dev The FEE_DISTRIBUTION_KEEPER role.\\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\\n */\\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\\\"FEE_DISTRIBUTION_KEEPER\\\"));\\n\\n /**\\n * @dev The ORDER_KEEPER role.\\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\\n */\\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\\\"ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The FROZEN_ORDER_KEEPER role.\\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\\n */\\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\\\"FROZEN_ORDER_KEEPER\\\"));\\n\\n /**\\n * @dev The PRICING_KEEPER role.\\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\\n */\\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\\\"PRICING_KEEPER\\\"));\\n /**\\n * @dev The LIQUIDATION_KEEPER role.\\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\\n */\\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\\\"LIQUIDATION_KEEPER\\\"));\\n /**\\n * @dev The ADL_KEEPER role.\\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\\n */\\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\\\"ADL_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_KEEPER role.\\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\\n */\\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\\\"CONTRIBUTOR_KEEPER\\\"));\\n /**\\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\\n */\\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\\\"CONTRIBUTOR_DISTRIBUTOR\\\"));\\n\\n /**\\n * @dev The CLAIM_ADMIN role.\\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\\n */\\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\\\"CLAIM_ADMIN\\\"));\\n /**\\n * @dev The MULTICHAIN_READER role.\\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\\n */\\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\\\"MULTICHAIN_READER\\\"));\\n}\\n\",\"keccak256\":\"0x9cdae2fd9f0dd3579ef80b29eccfe0b1107efc4e280870f86b0d764aa4c3d5f5\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleModule.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./RoleStore.sol\\\";\\n\\n/**\\n * @title RoleModule\\n * @dev Contract for role validation functions\\n */\\ncontract RoleModule {\\n RoleStore public immutable roleStore;\\n\\n /**\\n * @dev Constructor that initializes the role store for this contract.\\n *\\n * @param _roleStore The contract instance to use as the role store.\\n */\\n constructor(RoleStore _roleStore) {\\n roleStore = _roleStore;\\n }\\n\\n /**\\n * @dev Only allows the contract's own address to call the function.\\n */\\n modifier onlySelf() {\\n if (msg.sender != address(this)) {\\n revert Errors.Unauthorized(msg.sender, \\\"SELF\\\");\\n }\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\\n */\\n modifier onlyTimelockMultisig() {\\n _validateRole(Role.TIMELOCK_MULTISIG, \\\"TIMELOCK_MULTISIG\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\\n */\\n modifier onlyTimelockAdmin() {\\n _validateRole(Role.TIMELOCK_ADMIN, \\\"TIMELOCK_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyConfigKeeper() {\\n _validateRole(Role.CONFIG_KEEPER, \\\"CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\\n */\\n modifier onlyLimitedConfigKeeper() {\\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \\\"LIMITED_CONFIG_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTROLLER role to call the function.\\n */\\n modifier onlyController() {\\n _validateRole(Role.CONTROLLER, \\\"CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\\n */\\n modifier onlyGovTokenController() {\\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \\\"GOV_TOKEN_CONTROLLER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\\n */\\n modifier onlyRouterPlugin() {\\n _validateRole(Role.ROUTER_PLUGIN, \\\"ROUTER_PLUGIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\\n */\\n modifier onlyMarketKeeper() {\\n _validateRole(Role.MARKET_KEEPER, \\\"MARKET_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\\n */\\n modifier onlyFeeKeeper() {\\n _validateRole(Role.FEE_KEEPER, \\\"FEE_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\\n */\\n modifier onlyFeeDistributionKeeper() {\\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \\\"FEE_DISTRIBUTION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\\n */\\n modifier onlyOrderKeeper() {\\n _validateRole(Role.ORDER_KEEPER, \\\"ORDER_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\\n */\\n modifier onlyPricingKeeper() {\\n _validateRole(Role.PRICING_KEEPER, \\\"PRICING_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\\n */\\n modifier onlyLiquidationKeeper() {\\n _validateRole(Role.LIQUIDATION_KEEPER, \\\"LIQUIDATION_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\\n */\\n modifier onlyAdlKeeper() {\\n _validateRole(Role.ADL_KEEPER, \\\"ADL_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\\n */\\n modifier onlyContributorKeeper() {\\n _validateRole(Role.CONTRIBUTOR_KEEPER, \\\"CONTRIBUTOR_KEEPER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyContributorDistributor() {\\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \\\"CONTRIBUTOR_DISTRIBUTOR\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\\n */\\n modifier onlyClaimAdmin() {\\n _validateRole(Role.CLAIM_ADMIN, \\\"CLAIM_ADMIN\\\");\\n _;\\n }\\n\\n /**\\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\\n */\\n modifier onlyMultichainReader() {\\n _validateRole(Role.MULTICHAIN_READER, \\\"MULTICHAIN_READER\\\");\\n _;\\n }\\n\\n /**\\n * @dev Validates that the caller has the specified role.\\n *\\n * If the caller does not have the specified role, the transaction is reverted.\\n *\\n * @param role The key of the role to validate.\\n * @param roleName The name of the role to validate.\\n */\\n function _validateRole(bytes32 role, string memory roleName) internal view {\\n if (!roleStore.hasRole(msg.sender, role)) {\\n revert Errors.Unauthorized(msg.sender, roleName);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5a1903b81df17a1b663252445c860cda0c43fb03c8dce06f738d77f488654fed\",\"license\":\"BUSL-1.1\"},\"contracts/role/RoleStore.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"../utils/EnumerableValues.sol\\\";\\nimport \\\"./Role.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title RoleStore\\n * @dev Stores roles and their members.\\n */\\ncontract RoleStore {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableValues for EnumerableSet.AddressSet;\\n using EnumerableValues for EnumerableSet.Bytes32Set;\\n\\n EnumerableSet.Bytes32Set internal roles;\\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\\n // checking if an account has a role is a frequently used function\\n // roleCache helps to save gas by offering a more efficient lookup\\n // vs calling roleMembers[key].contains(account)\\n mapping(address => mapping (bytes32 => bool)) roleCache;\\n\\n modifier onlyRoleAdmin() {\\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\\n revert Errors.Unauthorized(msg.sender, \\\"ROLE_ADMIN\\\");\\n }\\n _;\\n }\\n\\n constructor() {\\n _grantRole(msg.sender, Role.ROLE_ADMIN);\\n }\\n\\n /**\\n * @dev Grants the specified role to the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to grant.\\n */\\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _grantRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Revokes the specified role from the given account.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role to revoke.\\n */\\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\\n _revokeRole(account, roleKey);\\n }\\n\\n /**\\n * @dev Returns true if the given account has the specified role.\\n *\\n * @param account The address of the account.\\n * @param roleKey The key of the role.\\n * @return True if the account has the role, false otherwise.\\n */\\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\\n return roleCache[account][roleKey];\\n }\\n\\n /**\\n * @dev Returns the number of roles stored in the contract.\\n *\\n * @return The number of roles.\\n */\\n function getRoleCount() external view returns (uint256) {\\n return roles.length();\\n }\\n\\n /**\\n * @dev Returns the keys of the roles stored in the contract.\\n *\\n * @param start The starting index of the range of roles to return.\\n * @param end The ending index of the range of roles to return.\\n * @return The keys of the roles.\\n */\\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\\n return roles.valuesAt(start, end);\\n }\\n\\n /**\\n * @dev Returns the number of members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @return The number of members of the role.\\n */\\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\\n return roleMembers[roleKey].length();\\n }\\n\\n /**\\n * @dev Returns the members of the specified role.\\n *\\n * @param roleKey The key of the role.\\n * @param start the start index, the value for this index will be included.\\n * @param end the end index, the value for this index will not be included.\\n * @return The members of the role.\\n */\\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\\n return roleMembers[roleKey].valuesAt(start, end);\\n }\\n\\n function _grantRole(address account, bytes32 roleKey) internal {\\n roles.add(roleKey);\\n roleMembers[roleKey].add(account);\\n roleCache[account][roleKey] = true;\\n }\\n\\n function _revokeRole(address account, bytes32 roleKey) internal {\\n roleMembers[roleKey].remove(account);\\n roleCache[account][roleKey] = false;\\n\\n if (roleMembers[roleKey].length() == 0) {\\n if (roleKey == Role.ROLE_ADMIN) {\\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\\n }\\n if (roleKey == Role.TIMELOCK_MULTISIG) {\\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaa7be1876450ec19568c0e12e4238332c96eb921974a19c0e4a6fe1fb943bf6d\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapHandler.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ISwapUtils.sol\\\";\\n\\ninterface ISwapHandler {\\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\\n}\\n\",\"keccak256\":\"0x1b727eec00a96759c36a3958f0eeb8a4c8a8905f557c4d0e986ad8edf7001e6b\",\"license\":\"BUSL-1.1\"},\"contracts/swap/ISwapUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../event/EventEmitter.sol\\\";\\nimport \\\"../bank/Bank.sol\\\";\\nimport \\\"../market/Market.sol\\\";\\n\\nimport \\\"../oracle/IOracle.sol\\\";\\nimport \\\"../pricing/ISwapPricingUtils.sol\\\";\\n\\ninterface ISwapUtils {\\n event SwapReverted(string reason, bytes reasonBytes);\\n\\n /**\\n * @param dataStore The contract that provides access to data stored on-chain.\\n * @param eventEmitter The contract that emits events.\\n * @param oracle The contract that provides access to price data from oracles.\\n * @param bank The contract providing the funds for the swap.\\n * @param key An identifying key for the swap.\\n * @param tokenIn The address of the token that is being swapped.\\n * @param amountIn The amount of the token that is being swapped.\\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\\n * @param receiver The address to which the swapped tokens should be sent.\\n * @param uiFeeReceiver The address of the ui fee receiver.\\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\\n */\\n struct SwapParams {\\n DataStore dataStore;\\n EventEmitter eventEmitter;\\n IOracle oracle;\\n Bank bank;\\n bytes32 key;\\n address tokenIn;\\n uint256 amountIn;\\n Market.Props[] swapPathMarkets;\\n uint256 minOutputAmount;\\n address receiver;\\n address uiFeeReceiver;\\n bool shouldUnwrapNativeToken;\\n ISwapPricingUtils.SwapPricingType swapPricingType;\\n }\\n}\\n\",\"keccak256\":\"0xc0b9aecf05709ec2e8775509336159685013c3e468ffe057bb75e26118878d1b\",\"license\":\"BUSL-1.1\"},\"contracts/token/IWNT.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title IWNT\\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\\n * The contract is named WNT instead of WETH for a more general reference name\\n * that can be used on any blockchain\\n */\\ninterface IWNT {\\n function deposit() external payable;\\n function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x366f887cceea33dba2247278d3827366cdcc3a3d7a2e3559fae430644ccbee02\",\"license\":\"BUSL-1.1\"},\"contracts/token/TokenUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../data/DataStore.sol\\\";\\nimport \\\"../data/Keys.sol\\\";\\nimport \\\"../error/ErrorUtils.sol\\\";\\nimport \\\"../utils/AccountUtils.sol\\\";\\n\\nimport \\\"./IWNT.sol\\\";\\n\\n/**\\n * @title TokenUtils\\n * @dev Library for token functions, helps with transferring of tokens and\\n * native token functions\\n */\\nlibrary TokenUtils {\\n using Address for address;\\n using SafeERC20 for IERC20;\\n\\n event TokenTransferReverted(string reason, bytes returndata);\\n event NativeTokenTransferReverted(string reason);\\n\\n /**\\n * @dev Returns the address of the WNT token.\\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\\n * @return The address of the WNT token.\\n */\\n function wnt(DataStore dataStore) internal view returns (address) {\\n return dataStore.getAddress(Keys.WNT);\\n }\\n\\n /**\\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\\n * @param token The address of the ERC20 token that is being transferred.\\n * @param receiver The address of the recipient of the `token` transfer.\\n * @param amount The amount of `token` to transfer.\\n */\\n function transfer(\\n DataStore dataStore,\\n address token,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\\n if (gasLimit == 0) {\\n revert Errors.EmptyTokenTranferGasLimit(token);\\n }\\n\\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n receiver,\\n amount,\\n gasLimit\\n );\\n\\n if (success0) { return; }\\n\\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\\n\\n if (holdingAddress == address(0)) {\\n revert Errors.EmptyHoldingAddress();\\n }\\n\\n // in case transfers to the receiver fail due to blacklisting or other reasons\\n // send the tokens to a holding address to avoid possible gaming through reverting\\n // transfers\\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\\n IERC20(token),\\n holdingAddress,\\n amount,\\n gasLimit\\n );\\n\\n if (success1) { return; }\\n\\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\\n emit TokenTransferReverted(reason, returndata);\\n\\n // throw custom errors to prevent spoofing of errors\\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\\n // do not cancel requests for specific errors\\n revert Errors.TokenTransferError(token, receiver, amount);\\n }\\n\\n function sendNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n\\n AccountUtils.validateReceiver(receiver);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * Deposits the specified amount of native token and sends the specified\\n * amount of wrapped native token to the specified receiver address.\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param receiver the address of the recipient of the wrapped native token transfer\\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\\n */\\n function depositAndSendWrappedNativeToken(\\n DataStore dataStore,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n address _wnt = wnt(dataStore);\\n IWNT(_wnt).deposit{value: amount}();\\n\\n transfer(\\n dataStore,\\n _wnt,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Withdraws the specified amount of wrapped native token and sends the\\n * corresponding amount of native token to the specified receiver address.\\n *\\n * limit the amount of gas forwarded so that a user cannot intentionally\\n * construct a token call that would consume all gas and prevent necessary\\n * actions like request cancellation from being executed\\n *\\n * @param dataStore the data store to use for storing and retrieving data\\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\\n * @param receiver the address of the recipient of the native token transfer\\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\\n */\\n function withdrawAndSendNativeToken(\\n DataStore dataStore,\\n address _wnt,\\n address receiver,\\n uint256 amount\\n ) internal {\\n if (amount == 0) { return; }\\n AccountUtils.validateReceiver(receiver);\\n\\n IWNT(_wnt).withdraw(amount);\\n\\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\\n\\n bool success;\\n // use an assembly call to avoid loading large data into memory\\n // input mem[in\\u2026(in+insize)]\\n // output area mem[out\\u2026(out+outsize))]\\n assembly {\\n success := call(\\n gasLimit, // gas limit\\n receiver, // receiver\\n amount, // value\\n 0, // in\\n 0, // insize\\n 0, // out\\n 0 // outsize\\n )\\n }\\n\\n if (success) { return; }\\n\\n // if the transfer failed, re-wrap the token and send it to the receiver\\n depositAndSendWrappedNativeToken(\\n dataStore,\\n receiver,\\n amount\\n );\\n }\\n\\n /**\\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\\n * address, with a gas limit to prevent the transfer from consuming all available gas.\\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\\n *\\n * @param token the ERC20 contract to transfer the tokens from\\n * @param to the address of the recipient of the token transfer\\n * @param amount the amount of tokens to transfer\\n * @param gasLimit the maximum amount of gas that the token transfer can consume\\n * @return a tuple containing a boolean indicating the success or failure of the\\n * token transfer, and a bytes value containing the return data from the token transfer\\n */\\n function nonRevertingTransferWithGasLimit(\\n IERC20 token,\\n address to,\\n uint256 amount,\\n uint256 gasLimit\\n ) internal returns (bool, bytes memory) {\\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\\n\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (!address(token).isContract()) {\\n return (false, \\\"Call to non-contract\\\");\\n }\\n }\\n\\n // some tokens do not revert on a failed transfer, they will return a boolean instead\\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\\n return (false, returndata);\\n }\\n\\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\\n // for these tokens, if success is true then the transfer should have completed\\n return (true, returndata);\\n }\\n\\n return (false, returndata);\\n }\\n}\\n\",\"keccak256\":\"0xc9583947413e24886ca4c77406471a606614dada46e0aacb9f7962f629171810\",\"license\":\"BUSL-1.1\"},\"contracts/utils/AccountUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary AccountUtils {\\n function validateAccount(address account) internal pure {\\n if (account == address(0)) {\\n revert Errors.EmptyAccount();\\n }\\n }\\n\\n function validateReceiver(address receiver) internal pure {\\n if (receiver == address(0)) {\\n revert Errors.EmptyReceiver();\\n }\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n return account.code.length > 0;\\n }\\n\\n}\\n\",\"keccak256\":\"0x9e83c9324530fc8e158a2ffc9abcc6b5d4985dd9c10c56d574700637aa49cfb1\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Array.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Array\\n * @dev Library for array functions\\n */\\nlibrary Array {\\n using SafeCast for int256;\\n\\n /**\\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\\n *\\n * @param arr the array to get the value from\\n * @param index the index of the element in the array\\n * @return the value of the element at the specified index in the array\\n */\\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\\n if (index < arr.length) {\\n return arr[index];\\n }\\n\\n return bytes32(0);\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\\n */\\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] != value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\\n */\\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] <= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\\n */\\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] < value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than the specified value, false otherwise\\n */\\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] >= value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\\n *\\n * @param arr the array to check the elements of\\n * @param value the value to compare the elements of the array to\\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\\n */\\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\\n for (uint256 i; i < arr.length; i++) {\\n if (arr[i] > value) {\\n return false;\\n }\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\\n *\\n * @param arr the array to get the median value from\\n * @return the median value of the elements in the given array\\n */\\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\\n if (arr.length % 2 == 1) {\\n return arr[arr.length / 2];\\n }\\n\\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\\n }\\n\\n /**\\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\\n *\\n * @param compactedValues the array of compacted values to get the uncompacted value from\\n * @param index the index of the uncompacted value in the array\\n * @param compactedValueBitLength the length of each compacted value, in bits\\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\\n * @return the uncompacted value at the specified index in the array of compacted values\\n */\\n function getUncompactedValue(\\n uint256[] memory compactedValues,\\n uint256 index,\\n uint256 compactedValueBitLength,\\n uint256 bitmask,\\n string memory label\\n ) internal pure returns (uint256) {\\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\\n\\n uint256 slotIndex = index / compactedValuesPerSlot;\\n if (slotIndex >= compactedValues.length) {\\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\\n }\\n\\n uint256 slotBits = compactedValues[slotIndex];\\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\\n\\n uint256 value = (slotBits >> offset) & bitmask;\\n\\n return value;\\n }\\n\\n /**\\n * Converts an array of bytes32 values to bytes.\\n * \\n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\\n * because it is expected to be the GMX_DATA_ACTION hash.\\n *\\n * @param dataList the array of bytes32 values to convert\\n * @return data the bytes array representing the input dataList\\n */\\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\\n bytes memory data;\\n\\n for (uint256 i = 1; i < dataList.length; i++) {\\n data = bytes.concat(data, bytes32(dataList[i]));\\n }\\n\\n return data;\\n }\\n}\\n\",\"keccak256\":\"0x95266ed524a93ab0bbc8cdea573a9a319da4e1e242d2806284062a5fd0ab9da3\",\"license\":\"BUSL-1.1\"},\"contracts/utils/BasicMulticall.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/ErrorUtils.sol\\\";\\n\\n/**\\n * @title BasicMulticall\\n */\\nabstract contract BasicMulticall {\\n /**\\n * @dev Receives and executes a batch of function calls on this contract.\\n */\\n function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n\\n for (uint256 i; i < data.length; i++) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n ErrorUtils.revertWithParsedMessage(result);\\n }\\n\\n results[i] = result;\\n }\\n\\n return results;\\n }\\n}\\n\",\"keccak256\":\"0xdf9d58a9b7d7b28be24bd2668da62ca377f6e1aa1e65111fd6da7cc6b5db1851\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Calc.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\n/**\\n * @title Calc\\n * @dev Library for math functions\\n */\\nlibrary Calc {\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n\\n // this method assumes that min is less than max\\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\\n uint256 magnitude = value.abs();\\n\\n if (magnitude < min) {\\n magnitude = min;\\n }\\n\\n if (magnitude > max) {\\n magnitude = max;\\n }\\n\\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\\n\\n return magnitude.toInt256() * sign;\\n }\\n\\n /**\\n * @dev Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\\n return (a + b - 1) / b;\\n }\\n\\n /**\\n * Calculates the result of dividing the first number by the second number,\\n * rounded up to the nearest integer.\\n * The rounding is purely on the magnitude of a, if a is negative the result\\n * is a larger magnitude negative\\n *\\n * @param a the dividend\\n * @param b the divisor\\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\\n */\\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\\n if (a < 0) {\\n return (a - b.toInt256() + 1) / b.toInt256();\\n }\\n\\n return (a + b.toInt256() - 1) / b.toInt256();\\n }\\n\\n /**\\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\\n if (b > 0) {\\n return a + b.abs();\\n }\\n\\n return a - b.abs();\\n }\\n\\n /**\\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\\n return a.toInt256() + b;\\n }\\n\\n /**\\n * @dev Calculates the absolute difference between two numbers.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the absolute difference between the two numbers\\n */\\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a - b : b - a;\\n }\\n\\n /**\\n * Adds two numbers together, the result is bounded to prevent overflows.\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the result of adding the two numbers together\\n */\\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or if the signs are different there should not be any overflows\\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\\n return a + b;\\n }\\n\\n // if adding `b` to `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n // if adding `b` to `a` would result in a value more than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n return a + b;\\n }\\n\\n /**\\n * Returns a - b, the result is bounded to prevent overflows.\\n * Note that this will revert if b is type(int256).min because of the usage of \\\"-b\\\".\\n *\\n * @param a the first number\\n * @param b the second number\\n * @return the bounded result of a - b\\n */\\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\\n // if either a or b is zero or the signs are the same there should not be any overflow\\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\\n return a - b;\\n }\\n\\n // if adding `-b` to `a` would result in a value greater than the max int256 value\\n // then return the max int256 value\\n if (a > 0 && -b >= type(int256).max - a) {\\n return type(int256).max;\\n }\\n\\n // if subtracting `b` from `a` would result in a value less than the min int256 value\\n // then return the min int256 value\\n if (a < 0 && -b <= type(int256).min - a) {\\n return type(int256).min;\\n }\\n\\n return a - b;\\n }\\n\\n\\n /**\\n * Converts the given unsigned integer to a signed integer, using the given\\n * flag to determine whether the result should be positive or negative.\\n *\\n * @param a the unsigned integer to convert\\n * @param isPositive whether the result should be positive (if true) or negative (if false)\\n * @return the signed integer representation of the given unsigned integer\\n */\\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\\n if (isPositive) {\\n return a.toInt256();\\n } else {\\n return -a.toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3848e1c51a6c77a1d6ec30bb052e97f6c39437110c773ebc06956ce5e4a54370\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Cast.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\n/**\\n * @title Cast\\n * @dev Library for casting functions\\n */\\nlibrary Cast {\\n function toBytes32(address value) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(value)));\\n }\\n\\n /**\\n * @dev Converts a bytes array to a uint256.\\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\\n * @param uint256AsBytes The bytes array representing the uint256 value.\\n * @return value The uint256 value obtained from the bytes array.\\n */\\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\\n uint256 length = uint256AsBytes.length;\\n\\n if(length > 32) {\\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\\n }\\n\\n if (length == 0) {\\n return 0;\\n }\\n\\n uint256 value;\\n\\n assembly {\\n value := mload(add(uint256AsBytes, 32))\\n }\\n\\n return value = value >> (8 * (32 - length));\\n }\\n\\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n }\\n\\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\\n b = new bytes(32);\\n// bytes memory expoBytes = new bytes(1);\\n// if (x < 0) {\\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\\n// } else {\\n// expoBytes[0] = bytes1(uint8(x));\\n// }\\n assembly { mstore(add(b, 32), x) }\\n return b;\\n// return expoBytes;\\n }\\n}\\n\",\"keccak256\":\"0x6b37c48c3e61545c7cb824d4bb0ee2342f235a3a61485d79f182e3abd4e36f19\",\"license\":\"BUSL-1.1\"},\"contracts/utils/EnumerableValues.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\n\\n/**\\n * @title EnumerableValues\\n * @dev Library to extend the EnumerableSet library with functions to get\\n * valuesAt for a range\\n */\\nlibrary EnumerableValues {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using EnumerableSet for EnumerableSet.UintSet;\\n\\n /**\\n * Returns an array of bytes32 values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of bytes32 values.\\n */\\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n bytes32[] memory items = new bytes32[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of address values from the given set, starting at the given\\n * start index and ending before the given end index.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index.\\n * @param end The ending index.\\n * @return An array of address values.\\n */\\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n address[] memory items = new address[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n\\n\\n /**\\n * Returns an array of uint256 values from the given set, starting at the given\\n * start index and ending before the given end index, the item at the end index will not be returned.\\n *\\n * @param set The set to get the values from.\\n * @param start The starting index (inclusive, item at the start index will be returned).\\n * @param end The ending index (exclusive, item at the end index will not be returned).\\n * @return An array of uint256 values.\\n */\\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\\n if (start >= set.length()) {\\n return new uint256[](0);\\n }\\n\\n uint256 max = set.length();\\n if (end > max) { end = max; }\\n\\n uint256[] memory items = new uint256[](end - start);\\n for (uint256 i = start; i < end; i++) {\\n items[i - start] = set.at(i);\\n }\\n\\n return items;\\n }\\n}\\n\",\"keccak256\":\"0x1e525ad5645bc649551fa3a7d000af1cec96221d7fe1cdc17cedaf942b018f0d\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Precision.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\n// there is a known issue with prb-math v3.x releases\\n// https://github.com/PaulRBerg/prb-math/issues/178\\n// due to this, either prb-math v2.x or v4.x versions should be used instead\\nimport \\\"prb-math/contracts/PRBMathUD60x18.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n/**\\n * @title Precision\\n * @dev Library for precision values and conversions\\n */\\nlibrary Precision {\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n using SignedMath for int256;\\n\\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\\n\\n uint256 public constant WEI_PRECISION = 10 ** 18;\\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\\n\\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n /**\\n * Applies the given factor to the given value and returns the result.\\n *\\n * @param value The value to apply the factor to.\\n * @param factor The factor to apply.\\n * @return The result of applying the factor to the value.\\n */\\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION);\\n }\\n\\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\\n return mulDiv(numerator, value, denominator);\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\\n return numerator > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, numerator, denominator);\\n }\\n\\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n function applyExponentFactor(\\n uint256 floatValue,\\n uint256 exponentFactor\\n ) internal pure returns (uint256) {\\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\\n if (floatValue < FLOAT_PRECISION) {\\n return 0;\\n }\\n\\n if (exponentFactor == FLOAT_PRECISION) {\\n return floatValue;\\n }\\n\\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\\n uint256 weiValue = PRBMathUD60x18.pow(\\n floatToWei(floatValue),\\n floatToWei(exponentFactor)\\n );\\n\\n return weiToFloat(weiValue);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\\n if (value == 0) { return 0; }\\n\\n if (roundUpMagnitude) {\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\\n }\\n\\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\\n }\\n\\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\\n return toFactor(value, divisor, false);\\n }\\n\\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\\n uint256 result = toFactor(value.abs(), divisor);\\n return value > 0 ? result.toInt256() : -result.toInt256();\\n }\\n\\n /**\\n * Converts the given value from float to wei.\\n *\\n * @param value The value to convert.\\n * @return The converted value in wei.\\n */\\n function floatToWei(uint256 value) internal pure returns (uint256) {\\n return value / FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given value from wei to float.\\n *\\n * @param value The value to convert.\\n * @return The converted value in float.\\n */\\n function weiToFloat(uint256 value) internal pure returns (uint256) {\\n return value * FLOAT_TO_WEI_DIVISOR;\\n }\\n\\n /**\\n * Converts the given number of basis points to float.\\n *\\n * @param basisPoints The number of basis points to convert.\\n * @return The converted value in float.\\n */\\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\\n }\\n}\\n\",\"keccak256\":\"0x061037475955fce184c335c269f030db585bbffddf00e4a0eff7b34da8a64029\",\"license\":\"BUSL-1.1\"},\"contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nlibrary StringUtils {\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xd9f72f3739ba7274dbad085fd196e408c1bbcdf62997813dc34a890ccfacc16a\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Uint256Mask.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../error/Errors.sol\\\";\\n\\nlibrary Uint256Mask {\\n struct Mask {\\n uint256 bits;\\n }\\n\\n function validateUniqueAndSetIndex(\\n Mask memory mask,\\n uint256 index,\\n string memory label\\n ) internal pure {\\n if (index >= 256) {\\n revert Errors.MaskIndexOutOfBounds(index, label);\\n }\\n\\n uint256 bit = 1 << index;\\n\\n if (mask.bits & bit != 0) {\\n revert Errors.DuplicatedIndex(index, label);\\n }\\n\\n mask.bits = mask.bits | bit;\\n }\\n}\\n\",\"keccak256\":\"0x96aaf43efa3a092b2d8d1e88addab6c31f5a7f526b84a290b9ba43e803592e01\",\"license\":\"BUSL-1.1\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xed164c95012964f5e125b5d2b2d00471a4bdee4def618cd1fcf341d196011b61\",\"license\":\"Unlicense\"},\"prb-math/contracts/PRBMathUD60x18.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"./PRBMath.sol\\\";\\n\\n/// @title PRBMathUD60x18\\n/// @author Paul Razvan Berg\\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\\n/// maximum values permitted by the Solidity type uint256.\\nlibrary PRBMathUD60x18 {\\n /// @dev Half the SCALE number.\\n uint256 internal constant HALF_SCALE = 5e17;\\n\\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\\n uint256 internal constant LOG2_E = 1_442695040888963407;\\n\\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\\n\\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\\n uint256 internal constant MAX_WHOLE_UD60x18 =\\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @notice Calculates the arithmetic average of x and y, rounding down.\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // The operations can never overflow.\\n unchecked {\\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\\n result = (x >> 1) + (y >> 1) + (x & y & 1);\\n }\\n }\\n\\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\\n ///\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n ///\\n /// Requirements:\\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function ceil(uint256 x) internal pure returns (uint256 result) {\\n if (x > MAX_WHOLE_UD60x18) {\\n revert PRBMathUD60x18__CeilOverflow(x);\\n }\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"SCALE - remainder\\\" but faster.\\n let delta := sub(SCALE, remainder)\\n\\n // Equivalent to \\\"x + delta * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := add(x, mul(delta, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\\n ///\\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n ///\\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDiv(x, SCALE, y);\\n }\\n\\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\\n function e() internal pure returns (uint256 result) {\\n result = 2_718281828459045235;\\n }\\n\\n /// @notice Calculates the natural exponent of x.\\n ///\\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n /// - x must be less than 133.084258667509499441.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp(uint256 x) internal pure returns (uint256 result) {\\n // Without this check, the value passed to \\\"exp2\\\" would be greater than 192.\\n if (x >= 133_084258667509499441) {\\n revert PRBMathUD60x18__ExpInputTooBig(x);\\n }\\n\\n // Do the fixed-point multiplication inline to save gas.\\n unchecked {\\n uint256 doubleScaleProduct = x * LOG2_E;\\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\\n }\\n }\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n ///\\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\\n ///\\n /// Requirements:\\n /// - x must be 192 or less.\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\\n if (x >= 192e18) {\\n revert PRBMathUD60x18__Exp2InputTooBig(x);\\n }\\n\\n unchecked {\\n // Convert x to the 192.64-bit fixed-point format.\\n uint256 x192x64 = (x << 64) / SCALE;\\n\\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\\n result = PRBMath.exp2(x192x64);\\n }\\n }\\n\\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\\n function floor(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n // Equivalent to \\\"x % SCALE\\\" but faster.\\n let remainder := mod(x, SCALE)\\n\\n // Equivalent to \\\"x - remainder * (remainder > 0 ? 1 : 0)\\\" but faster.\\n result := sub(x, mul(remainder, gt(remainder, 0)))\\n }\\n }\\n\\n /// @notice Yields the excess beyond the floor of x.\\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\\n function frac(uint256 x) internal pure returns (uint256 result) {\\n assembly {\\n result := mod(x, SCALE)\\n }\\n }\\n\\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\\n ///\\n /// @dev Requirements:\\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\\n ///\\n /// @param x The basic integer to convert.\\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\\n function fromUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__FromUintOverflow(x);\\n }\\n result = x * SCALE;\\n }\\n }\\n\\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\\n ///\\n /// @dev Requirements:\\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\\n ///\\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n unchecked {\\n // Checking for overflow this way is faster than letting Solidity do it.\\n uint256 xy = x * y;\\n if (xy / x != y) {\\n revert PRBMathUD60x18__GmOverflow(x, y);\\n }\\n\\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\\n // during multiplication. See the comments within the \\\"sqrt\\\" function.\\n result = PRBMath.sqrt(xy);\\n }\\n }\\n\\n /// @notice Calculates 1 / x, rounding toward zero.\\n ///\\n /// @dev Requirements:\\n /// - x cannot be zero.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\\n function inv(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // 1e36 is SCALE * SCALE.\\n result = 1e36 / x;\\n }\\n }\\n\\n /// @notice Calculates the natural logarithm of x.\\n ///\\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\\n function ln(uint256 x) internal pure returns (uint256 result) {\\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\\n // can return is 196205294292027477728.\\n unchecked {\\n result = (log2(x) * SCALE) / LOG2_E;\\n }\\n }\\n\\n /// @notice Calculates the common logarithm of x.\\n ///\\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\\n ///\\n /// Requirements:\\n /// - All from \\\"log2\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"log2\\\".\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log10(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n\\n // Note that the \\\"mul\\\" in this block is the assembly multiplication operation, not the \\\"mul\\\" function defined\\n // in this contract.\\n // prettier-ignore\\n assembly {\\n switch x\\n case 1 { result := mul(SCALE, sub(0, 18)) }\\n case 10 { result := mul(SCALE, sub(1, 18)) }\\n case 100 { result := mul(SCALE, sub(2, 18)) }\\n case 1000 { result := mul(SCALE, sub(3, 18)) }\\n case 10000 { result := mul(SCALE, sub(4, 18)) }\\n case 100000 { result := mul(SCALE, sub(5, 18)) }\\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\\n case 1000000000000000000 { result := 0 }\\n case 10000000000000000000 { result := SCALE }\\n case 100000000000000000000 { result := mul(SCALE, 2) }\\n case 1000000000000000000000 { result := mul(SCALE, 3) }\\n case 10000000000000000000000 { result := mul(SCALE, 4) }\\n case 100000000000000000000000 { result := mul(SCALE, 5) }\\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\\n default {\\n result := MAX_UD60x18\\n }\\n }\\n\\n if (result == MAX_UD60x18) {\\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\\n unchecked {\\n result = (log2(x) * SCALE) / 3_321928094887362347;\\n }\\n }\\n }\\n\\n /// @notice Calculates the binary logarithm of x.\\n ///\\n /// @dev Based on the iterative approximation algorithm.\\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\\n ///\\n /// Requirements:\\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\\n ///\\n /// Caveats:\\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\\n function log2(uint256 x) internal pure returns (uint256 result) {\\n if (x < SCALE) {\\n revert PRBMathUD60x18__LogInputTooSmall(x);\\n }\\n unchecked {\\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\\n\\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\\n // because n is maximum 255 and SCALE is 1e18.\\n result = n * SCALE;\\n\\n // This is y = x * 2^(-n).\\n uint256 y = x >> n;\\n\\n // If y = 1, the fractional part is zero.\\n if (y == SCALE) {\\n return result;\\n }\\n\\n // Calculate the fractional part via the iterative approximation.\\n // The \\\"delta >>= 1\\\" part is equivalent to \\\"delta /= 2\\\", but shifting bits is faster.\\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\\n y = (y * y) / SCALE;\\n\\n // Is y^2 > 2 and so in the range [2,4)?\\n if (y >= 2 * SCALE) {\\n // Add the 2^(-m) factor to the logarithm.\\n result += delta;\\n\\n // Corresponds to z/2 on Wikipedia.\\n y >>= 1;\\n }\\n }\\n }\\n }\\n\\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\\n /// fixed-point number.\\n /// @dev See the documentation for the \\\"PRBMath.mulDivFixedPoint\\\" function.\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n result = PRBMath.mulDivFixedPoint(x, y);\\n }\\n\\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\\n function pi() internal pure returns (uint256 result) {\\n result = 3_141592653589793238;\\n }\\n\\n /// @notice Raises x to the power of y.\\n ///\\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\\n ///\\n /// Requirements:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n ///\\n /// Caveats:\\n /// - All from \\\"exp2\\\", \\\"log2\\\" and \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n if (x == 0) {\\n result = y == 0 ? SCALE : uint256(0);\\n } else {\\n result = exp2(mul(log2(x), y));\\n }\\n }\\n\\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\\n /// famous algorithm \\\"exponentiation by squaring\\\".\\n ///\\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\\n ///\\n /// Requirements:\\n /// - The result must fit within MAX_UD60x18.\\n ///\\n /// Caveats:\\n /// - All from \\\"mul\\\".\\n /// - Assumes 0^0 is 1.\\n ///\\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The exponent as an uint256.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n // Calculate the first iteration of the loop in advance.\\n result = y & 1 > 0 ? x : SCALE;\\n\\n // Equivalent to \\\"for(y /= 2; y > 0; y /= 2)\\\" but faster.\\n for (y >>= 1; y > 0; y >>= 1) {\\n x = PRBMath.mulDivFixedPoint(x, x);\\n\\n // Equivalent to \\\"y % 2 == 1\\\" but faster.\\n if (y & 1 > 0) {\\n result = PRBMath.mulDivFixedPoint(result, x);\\n }\\n }\\n }\\n\\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\\n function scale() internal pure returns (uint256 result) {\\n result = SCALE;\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Requirements:\\n /// - x must be less than MAX_UD60x18 / SCALE.\\n ///\\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n if (x > MAX_UD60x18 / SCALE) {\\n revert PRBMathUD60x18__SqrtOverflow(x);\\n }\\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\\n result = PRBMath.sqrt(x * SCALE);\\n }\\n }\\n\\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\\n /// @return result The same number in basic integer form.\\n function toUint(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n result = x / SCALE;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2180489de7680a79844dd5ef145f800e4f68e515e0e89409242f0187dbbd657b\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x61012060405234801561001157600080fd5b5060405161508238038061508283398101604081905261003091610071565b6001600160a01b0391821660805293811660a05291821660e0528116610100521660c0526100e6565b6001600160a01b038116811461006e57600080fd5b50565b600080600080600060a0868803121561008957600080fd5b855161009481610059565b60208701519095506100a581610059565b60408701519094506100b681610059565b60608701519093506100c781610059565b60808701519092506100d881610059565b809150509295509295909350565b60805160a05160c05160e05161010051614e7f610203600039600081816101f50152818161189501526121a6015260008181610289015281816107d2015281816109a6015281816110aa0152818161166801528181611dac01528181611ef40152818161230f015281816124c001526128da0152600081816104270152818161068a01528181610c4b01528181611256015281816112ca015281816113d901528181611b33015281816123cb01528181612670015281816127c601528181612b5801528181612f6a01528181612f9f015281816131d0015261320401526000818161032201528181612e830152612f0101526000818161022901528181610503015281816119900152818161204c0152612bf90152614e7f6000f3fe608060405234801561001057600080fd5b50600436106101805760003560e01c8063208dd1ff146101855780632a083ca31461019a5780632ab148dd146101b7578063314907c1146101ca57806331847c96146101dd578063392bf7f6146101f05780634a4a7b04146102245780634e2ba52d1461024b5780635588ec5a1461025e578063569936a414610271578063660d0d67146102845780636d00753e146102ab578063781cc3d3146102be57806378b79025146102d15780637ed67107146102e4578063881be502146102f7578063990200cb1461030a5780639ff78c301461031d578063a6a58fab14610344578063ac9650d814610357578063ad4e4ab214610377578063b5256f381461038a578063b97177941461039d578063cd63bfa5146103b0578063cdb07a4f146103c3578063d0b91b01146103d6578063d597d570146103e9578063db477adc146103fc578063e38335e51461040f578063f3388e7514610422578063f373d4b914610449578063feca03a51461045c575b600080fd5b6101986101933660046138e4565b61046f565b005b6101a46206978081565b6040519081526020015b60405180910390f35b6101986101c5366004613956565b61061f565b6101986101d83660046139ba565b610703565b6101986101eb3660046139ed565b610878565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b6040516101ae9190613a2f565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b610198610259366004613a43565b610af7565b61019861026c366004613a7c565b610c22565b61019861027f366004613b12565b610cc7565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b6101986102b9366004613b71565b610ee2565b6101986102cc366004613bbb565b61122e565b6101986102df366004613bd4565b6112b6565b6101986102f2366004613c00565b611490565b6101986103053660046139ba565b611816565b610198610318366004613a43565b611938565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b610198610352366004613c5e565b611a6a565b61036a610365366004613cef565b611c35565b6040516101ae9190613ddc565b610198610385366004613e07565b611d48565b610198610398366004613e4b565b611e93565b6101986103ab366004613a43565b611ff4565b6101986103be3660046139ba565b612127565b6101986103d13660046139ba565b612246565b6101a46103e4366004613ea0565b6123b1565b6101986103f7366004613e07565b61245c565b61019861040a366004613c5e565b6125a7565b61019861041d366004613ea0565b61279d565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b610198610457366004613f52565b612845565b6101a461046a366004613956565b612b3e565b6104ec6040516020016104a79060208082526011908201527054494d454c4f434b5f4d554c544953494760781b604082015260600190565b604051602081830303815290604052805190602001206040518060400160405280601181526020017054494d454c4f434b5f4d554c544953494760781b815250612be2565b60405163208dd1ff60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063208dd1ff9061053a9085908590600401613fe5565b600060405180830381600087803b15801561055457600080fd5b505af1158015610568573d6000803e3d6000fd5b505050506105746137d7565b8051610581906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516105ae9160009086612cfb565b60808101516105be906001612c96565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516105ee9160009085612d58565b61061a6040518060400160405280600a8152602001695265766f6b65526f6c6560b01b81525082612dab565b505050565b61067360405160200161063190613ffe565b604051602081830303815290604052805190602001206040518060400160405280600e81526020016d2a24a6a2a627a1a5afa0a226a4a760911b815250612be2565b60405163134008d360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063134008d3906106ca908890600090899089908990899060040161404f565b600060405180830381600087803b1580156106e457600080fd5b505af11580156106f8573d6000803e3d6000fd5b505050505050505050565b61071560405160200161063190613ffe565b6001600160a01b038316610747578260405163cb9339d560e01b815260040161073e9190613a2f565b60405180910390fd5b6000604051602001610779906020808252600c908201526b2322a2afa922a1a2a4ab22a960a11b604082015260600190565b60405160208183030381529060405280519060200120846040516024016107a192919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905290506107f97f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6108016137d7565b805161080e906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161083b9160009088612cfb565b6108716040518060400160405280601481526020017329b4b3b730b629b2ba2332b2a932b1b2b4bb32b960611b81525082612dab565b5050505050565b61088a60405160200161063190613ffe565b836108aa57846040516318b900b360e21b815260040161073e9190613a2f565b60408051600280825260608201909252600091816020015b60608152602001906001900390816108c25790505090506108e286613040565b856040516024016108f49291906140b9565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b17905281518290600090610931576109316140c7565b6020026020010181905250610945866130be565b846040516024016109579291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110610996576109966140c7565b60200260200101819052506109cd7f0000000000000000000000000000000000000000000000000000000000000000828585613101565b6109d56137d7565b80516109e2906001612c96565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610a0d916000908a612cfb565b6080810151610a1d906001612c96565b60408051808201909152601081526f195919d951185d1854dd1c99585b525960821b60208201526080820151610a569160009089612d58565b6020810151610a66906001612c96565b610ab560006040518060400160405280601b81526020017a656467654461746153747265616d546f6b656e446563696d616c7360281b815250878460200151612d58909392919063ffffffff16565b610aee604051806040016040528060178152602001765369676e616c536574456467654461746153747265616d60481b81525082612dab565b50505050505050565b610b0960405160200161063190613ffe565b6001600160a01b038416610b3057604051634e6e36d560e11b815260040160405180910390fd5b621a5e00831015610b575760405163961b402560e01b81526004810184905260240161073e565b600083604051602401610b6c91815260200190565b60408051601f198184030181529190526020810180516001600160e01b0316630f8c394b60e01b1790529050610ba485828585612f68565b610bac6137d7565b6020810151610bbc906001612c96565b610bf86000604051806040016040528060088152602001671a5b9d195c9d985b60c21b815250878460200151612d58909392919063ffffffff16565b610c1a604051806060016040528060268152602001614dd96026913982612dab565b505050505050565b610c3460405160200161063190613ffe565b60405163d0663e6160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d0663e6190610c8d9089906000908a908a908a908a908a906004016141ff565b600060405180830381600087803b158015610ca757600080fd5b505af1158015610cbb573d6000803e3d6000fd5b50505050505050505050565b610cd960405160200161063190613ffe565b6001600160a01b038616610d0057604051634e6e36d560e11b815260040160405180910390fd5b6001600160a01b038516610d275760405163066f53b160e01b815260040160405180910390fd5b6001600160a01b038416610d4e5760405163d551823d60e01b815260040160405180910390fd5b82600003610d6f576040516301d6f7b160e01b815260040160405180910390fd5b6000858585604051602401610d86939291906142af565b60408051601f198184030181529190526020810180516001600160e01b0316632f1a9acf60e11b1790529050610dbe87828585612f68565b610dc66137d7565b8051610dd3906003612c96565b6040805180820190915260068152651d185c99d95d60d21b60208201528151610dff916000908b612cfb565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610e2a916001908a612cfb565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151610e589160029089612cfb565b6020810151610e68906001612c96565b610ea2600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151612d58909392919063ffffffff16565b610ed8604051806040016040528060148152602001735369676e616c5769746864726177546f6b656e7360601b81525082612dab565b5050505050505050565b610ef460405160200161063190613ffe565b68327cb2734119d3b7a9601e1b831115610f4957604051602001610f17906142d3565b6040516020818303038152906040528051906020012083604051635ebb87c960e01b815260040161073e9291906140b9565b60408051600380825260808201909252600091816020015b6060815260200190600190039081610f61579050509050610f81876132e0565b86604051602401610f939291906140b9565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b17905281518290600090610fd057610fd06140c7565b6020026020010181905250610fe487613314565b85604051602401610ff69291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110611035576110356140c7565b602002602001018190525061104987613350565b8460405160240161105b9291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b17905281518290600290811061109a5761109a6140c7565b60200260200101819052506110d17f0000000000000000000000000000000000000000000000000000000000000000828585613101565b6110d96137d7565b80516110e6906001612c96565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611111916000908b612cfb565b6080810151611121906001612c96565b60408051808201909152600681526519995959125960d21b60208201526080820151611150916000908a612d58565b6020810151611160906002612c96565b6111a86000604051806040016040528060148152602001733230ba30a9ba3932b0b6a6bab63a34b83634b2b960611b815250888460200151612d58909392919063ffffffff16565b6111f960016040518060400160405280601f81526020017f6461746153747265616d537072656164526564756374696f6e466163746f7200815250878460200151612d58909392919063ffffffff16565b610ed8604051806040016040528060138152602001725369676e616c5365744461746153747265616d60681b81525082612dab565b61124060405160200161063190613ffe565b60405163c4d252f560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c4d252f590602401600060405180830381600087803b1580156112a257600080fd5b505af1158015610871573d6000803e3d6000fd5b6112c860405160200161063190613ffe565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134a9190614316565b831161136c576040516373586edb60e11b81526004810184905260240161073e565b6206978083111561139357604051633ebd9bc360e21b81526004810184905260240161073e565b6000836040516024016113a891815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166364d6235360e01b17905290506114007f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6114086137d7565b6020810151611418906001612c96565b61145960006040518060400160405280600d81526020016c74696d656c6f636b44656c617960981b815250878460200151612d58909392919063ffffffff16565b61087160405180604001604052806015815260200174496e63726561736554696d656c6f636b44656c617960581b81525082612dab565b6114a260405160200161063190613ffe565b60408051600480825260a08201909252600091816020015b60608152602001906001900390816114ba5790505090506114da88613361565b876040516024016114ec92919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905281518290600090611529576115296140c7565b602002602001018190525061153d88613391565b8660405160240161154f9291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b17905281518290600190811061158e5761158e6140c7565b60200260200101819052506115a2886133cc565b856040516024016115b49291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b1790528151829060029081106115f3576115f36140c7565b60200260200101819052506116078861340f565b846040516024016116199291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906003908110611658576116586140c7565b602002602001018190525061168f7f0000000000000000000000000000000000000000000000000000000000000000828585613101565b6116976137d7565b80516116a4906002612c96565b6040805180820190915260058152643a37b5b2b760d91b602082015281516116cf916000908c612cfb565b6040805180820190915260098152681c1c9a58d95199595960ba1b602082015281516116fe916001908b612cfb565b602081015161170e906003612c96565b611755600060405180604001604052806013815260200172383934b1b2a332b2b226bab63a34b83634b2b960691b815250898460200151612d58909392919063ffffffff16565b6117a360016040518060400160405280601a815260200179383934b1b2a332b2b22432b0b93a3132b0ba223ab930ba34b7b760311b815250888460200151612d58909392919063ffffffff16565b6117e260026040518060400160405280600b81526020016a737461626c65507269636560a81b815250878460200151612d58909392919063ffffffff16565b6106f86040518060400160405280601281526020017114da59db985b14d95d141c9a58d95199595960721b81525082612dab565b61182860405160200161063190613ffe565b6001600160a01b038316611851578260405163c1b14c9160e01b815260040161073e9190613a2f565b6000836040516024016118649190613a2f565b60408051601f198184030181529190526020810180516001600160e01b0316630e316ab760e01b17905290506118bc7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6118c46137d7565b80516118d1906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516118fe9160009088612cfb565b6108716040518060400160405280601881526020017729b4b3b730b62932b6b7bb32a7b930b1b632a9b4b3b732b960411b81525082612dab565b61194a60405160200161063190613ffe565b6000848460405160240161195f929190613fe5565b60408051601f198184030181529190526020810180516001600160e01b0316632ac9d0b760e21b17905290506119b77f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6119bf6137d7565b80516119cc906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516119f99160009089612cfb565b6080810151611a09906001612c96565b604080518082019091526007815266726f6c654b657960c81b60208201526080820151611a399160009088612d58565b610c1a6040518060400160405280600f81526020016e5369676e616c4772616e74526f6c6560881b81525082612dab565b611a7c60405160200161063190613ffe565b6001600160a01b038516611aa3576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b038416611aca5760405163d551823d60e01b815260040160405180910390fd5b82600003611aeb57604051630d1bbc9560e01b815260040160405180910390fd5b6000858585604051602401611b02939291906142af565b60408051601f198184030181529190526020810180516001600160e01b0316632bae9a3560e11b1790529050611b5a7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b611b626137d7565b8051611b6f906002612c96565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611b9b916000908a612cfb565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151611bc99160019089612cfb565b6020810151611bd9906001612c96565b611c13600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151612d58909392919063ffffffff16565b610aee604051806060016040528060248152602001614e266024913982612dab565b6060816001600160401b03811115611c4f57611c4f6140a3565b604051908082528060200260200182016040528015611c8257816020015b6060815260200190600190039081611c6d5790505b50905060005b82811015611d415760008030868685818110611ca657611ca66140c7565b9050602002810190611cb8919061432f565b604051611cc6929190614375565b600060405180830381855af49150503d8060008114611d01576040519150601f19603f3d011682016040523d82523d6000602084013e611d06565b606091505b509150915081611d1957611d1981613441565b80848481518110611d2c57611d2c6140c7565b60209081029190910101525050600101611c88565b5092915050565b611d5a60405160200161063190613ffe565b6000611d658561347a565b6040516024810191909152841515604482015260640160408051601f198184030181529190526020810180516001600160e01b031663abfdcced60e01b1790529050611dd37f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b611ddb6137d7565b8051611de8906001612c96565b604080518082019091526008815267383937bb34b232b960c11b60208201528151611e169160009089612cfb565b6060810151611e26906001612c96565b60408051808201909152600581526476616c756560d81b60208201526060820151611e5491600090886134b9565b610c1a6040518060400160405280601d81526020017f5369676e616c53657441746f6d69634f7261636c6550726f766964657200000081525082612dab565b611ea560405160200161063190613ffe565b6000611eb1868661350e565b84604051602401611ec392919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b1790529050611f1b7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b611f236137d7565b8051611f30906003612c96565b6040805180820190915260068152656f7261636c6560d01b60208201528151611f5c916000908a612cfb565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611f879160019089612cfb565b604080518082019091526008815267383937bb34b232b960c11b60208201528151611fb59160029088612cfb565b610aee6040518060400160405280601f81526020017f5369676e616c5365744f7261636c6550726f7669646572466f72546f6b656e0081525082612dab565b61200660405160200161063190613ffe565b6000848460405160240161201b929190613fe5565b60408051601f198184030181529190526020810180516001600160e01b031663208dd1ff60e01b17905290506120737f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b61207b6137d7565b8051612088906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516120b59160009089612cfb565b60808101516120c5906001612c96565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516120f59160009088612d58565b610c1a6040518060400160405280601081526020016f5369676e616c5265766f6b65526f6c6560801b81525082612dab565b61213960405160200161063190613ffe565b6001600160a01b038316612162578260405163c1b14c9160e01b815260040161073e9190613a2f565b6000836040516024016121759190613a2f565b60408051601f198184030181529190526020810180516001600160e01b03166375896b0f60e11b17905290506121cd7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6121d56137d7565b80516121e2906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161220f9160009088612cfb565b6108716040518060400160405280601581526020017429b4b3b730b620b23227b930b1b632a9b4b3b732b960591b81525082612dab565b61225860405160200161063190613ffe565b6001600160a01b0383166122815782604051630f773b1f60e31b815260040161073e9190613a2f565b60006040516020016122b6906020808252600f908201526e484f4c44494e475f4144445245535360881b604082015260600190565b60405160208183030381529060405280519060200120846040516024016122de92919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905290506123367f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b61233e6137d7565b805161234b906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516123789160009088612cfb565b610871604051806040016040528060178152602001765369676e616c536574486f6c64696e674164647265737360481b81525082612dab565b60405163b1c5f42760e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b1c5f4279061240e908c908c908a908a908e908e908c908c906004016143b7565b602060405180830381865afa15801561242b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244f9190614316565b9998505050505050505050565b61246e60405160200161063190613ffe565b6000612479856135a3565b6040516024810191909152841515604482015260640160408051601f198184030181529190526020810180516001600160e01b031663abfdcced60e01b17905290506124e77f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6124ef6137d7565b80516124fc906001612c96565b604080518082019091526008815267383937bb34b232b960c11b6020820152815161252a9160009089612cfb565b606081015161253a906001612c96565b60408051808201909152600581526476616c756560d81b6020820152606082015161256891600090886134b9565b610c1a6040518060400160405280601e81526020017f5369676e616c5365744f7261636c6550726f7669646572456e61626c6564000081525082612dab565b6125b960405160200161063190613ffe565b6001600160a01b0385166125e0576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b03841661260757604051639ab5d12760e01b815260040160405180910390fd5b826000036126285760405163b3d3553960e01b815260040160405180910390fd5b600085858560405160240161263f939291906142af565b60408051601f198184030181529190526020810180516001600160e01b031663f128024b60e01b17905290506126977f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b61269f6137d7565b80516126ac906002612c96565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126d8916000908a612cfb565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b6020820152815161270c9160019089612cfb565b602081015161271c906001612c96565b61275f60006040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250878460200151612d58909392919063ffffffff16565b610aee6040518060400160405280601c81526020017b14da59db985b1499591d58d953195b9d125b5c1858dd105b5bdd5b9d60221b81525082612dab565b6127af60405160200161063190613ffe565b60405163e38335e560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e38335e590612809908b908b908b908b908b908b908b908b906004016143b7565b600060405180830381600087803b15801561282357600080fd5b505af1158015612837573d6000803e3d6000fd5b505050505050505050505050565b61285760405160200161063190613ffe565b6001600160a01b03871661287e57604051634e6e36d560e11b815260040160405180910390fd5b8483146128a257604051630a6a4f7160e21b815261073e90869085906004016140b9565b60005b858110156129de5760008787838181106128c1576128c16140c7565b90506020020160208101906128d6919061440b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c769d1a16040516020016129419060208082526016908201527510d3d395149250955513d497d513d2d15397d31254d560521b604082015260600190565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161297592919061408c565b602060405180830381865afa158015612992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b69190614426565b6129d55780604051634a59130960e01b815260040161073e9190613a2f565b506001016128a5565b506000868686866040516024016129f89493929190614443565b60408051601f198184030181529190526020810180516001600160e01b031663127db19160e21b1790529050612a3088828585612f68565b612a386137d7565b8051612a459060016135e3565b612aa7600060405180604001604052806006815260200165746f6b656e7360d01b8152508a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050865194939291505061364d565b6020810151612ab79060016135e3565b612b1c600060405180604001604052806007815260200166616d6f756e747360c81b815250888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050602085015192919061364d565b6106f8604051806060016040528060278152602001614dff6027913982612dab565b604051638065657f60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638065657f90612b9790899085908a908a908a908a9060040161404f565b602060405180830381865afa158015612bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd89190614316565b9695505050505050565b60405163ac4ab3fb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac4ab3fb90612c309033908690600401613fe5565b602060405180830381865afa158015612c4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c719190614426565b612c9257338160405163a35b150b60e01b815260040161073e929190614475565b5050565b806001600160401b03811115612cae57612cae6140a3565b604051908082528060200260200182016040528015612cf457816020015b604080518082019091526060815260006020820152815260200190600190039081612ccc5790505b5090915250565b8184600001518481518110612d1257612d126140c7565b6020026020010151600001819052508084600001518481518110612d3857612d386140c7565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110612d6f57612d6f6140c7565b6020026020010151600001819052508084600001518481518110612d9557612d956140c7565b6020026020010151602001818152505050505050565b612db36137d7565b600083604051602001612dc691906144a1565b604051602081830303815290604052805190602001209050612df660018360800151612c9690919063ffffffff16565b604080518082019091526009815268616374696f6e4b657960b81b60208201526080830151612e289160009084612d58565b60c0820151612e3890600161369f565b60408051808201909152600b81526a1858dd1a5bdb931858995b60aa1b602082015260c0830151612e6c9160009087613701565b604051630937807960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906324de01e490612eba9084908690600401614bc5565b600060405180830381600087803b158015612ed457600080fd5b505af1158015612ee8573d6000803e3d6000fd5b505060405163483624fb60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063906c49f69150612f3a9087908790600401614c08565b600060405180830381600087803b158015612f5457600080fd5b505af1158015610ed8573d6000803e3d6000fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a8560008686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614316565b6040518763ffffffff1660e01b8152600401612f3a96959493929190614c2d565b600060405160200161307990602080825260139082015272115111d157d110551057d4d51491505357d251606a1b604082015260600190565b60405160208183030381529060405280519060200120826040516020016130a192919061408c565b604051602081830303815290604052805190602001209050919050565b6000604051602001613079906020808252601f908201527f454447455f444154415f53545245414d5f544f4b454e5f444543494d414c5300604082015260600190565b82516000816001600160401b0381111561311d5761311d6140a3565b604051908082528060200260200182016040528015613146578160200160208202803683370190505b50905060005b828110156131875786828281518110613167576131676140c7565b6001600160a01b039092166020928302919091019091015260010161314c565b506000826001600160401b038111156131a2576131a26140a3565b6040519080825280602002602001820160405280156131cb578160200160208202803683370190505b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb083838989897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613260573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132849190614316565b6040518763ffffffff1660e01b81526004016132a596959493929190614ca4565b600060405180830381600087803b1580156132bf57600080fd5b505af11580156132d3573d6000803e3d6000fd5b5050505050505050505050565b6000604051602001613079906020808252600e908201526d1110551057d4d51491505357d25160921b604082015260600190565b6000604051602001613079906020808252601690820152752220aa20afa9aa2922a0a6afa6aaa62a24a82624a2a960511b604082015260600190565b6000604051602001613079906142d3565b6000604051602001613079906020808252600a908201526914149250d157d191515160b21b604082015260600190565b600060405160200161307990602080825260159082015274282924a1a2afa322a2a22fa6aaa62a24a82624a2a960591b604082015260600190565b6000604051602001613079906020808252601d908201527f50524943455f464545445f4845415254424541545f4455524154494f4e000000604082015260600190565b6000604051602001613079906020808252600c908201526b535441424c455f505249434560a01b604082015260600190565b60008061344d8361373e565b915091508015613471578160405162461bcd60e51b815260040161073e91906144a1565b61061a836137ce565b60006040516020016130799060208082526019908201527824a9afa0aa27a6a4a1afa7a920a1a622afa82927ab24a222a960391b604082015260600190565b81846000015184815181106134d0576134d06140c7565b60200260200101516000018190525080846000015184815181106134f6576134f66140c7565b60209081029190910181015191151591015250505050565b600060405160200161354d9060208082526019908201527827a920a1a622afa82927ab24a222a92fa327a92faa27a5a2a760391b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800160405160208183030381529060405280519060200120905092915050565b6000604051602001613079906020808252601a90820152791254d7d3d49050d31157d41493d59251115497d153905093115160321b604082015260600190565b806001600160401b038111156135fb576135fb6140a3565b60405190808252806020026020018201604052801561364057816020015b60408051808201909152606080825260208201528152602001906001900390816136195790505b5082602001819052505050565b8184602001518481518110613664576136646140c7565b602002602001015160000181905250808460200151848151811061368a5761368a6140c7565b60200260200101516020018190525050505050565b806001600160401b038111156136b7576136b76140a3565b604051908082528060200260200182016040528015612cf457816020015b60408051808201909152606080825260208201528152602001906001900390816136d557505090915250565b8184600001518481518110613718576137186140c7565b602002602001015160000181905250808460000151848151811061368a5761368a6140c7565b60606000604483511015613765575050604080516020810190915260008082529092909150565b6000613772846020015190565b90506307b9e43360e51b6001600160e01b03198216016137b157600484019350838060200190518101906137a69190614d2f565b946001945092505050565b600060405180602001604052806000815250909250925050915091565b80518060208301fd5b604080516101208101909152606060e0820181815261010083019190915281908152602001613819604051806040016040528060608152602001606081525090565b815260200161383b604051806040016040528060608152602001606081525090565b815260200161385d604051806040016040528060608152602001606081525090565b815260200161387f604051806040016040528060608152602001606081525090565b81526020016138a1604051806040016040528060608152602001606081525090565b81526020016138c3604051806040016040528060608152602001606081525090565b905290565b80356001600160a01b03811681146138df57600080fd5b919050565b600080604083850312156138f757600080fd5b613900836138c8565b946020939093013593505050565b60008083601f84011261392057600080fd5b5081356001600160401b0381111561393757600080fd5b60208301915083602082850101111561394f57600080fd5b9250929050565b60008060008060006080868803121561396e57600080fd5b613977866138c8565b945060208601356001600160401b0381111561399257600080fd5b61399e8882890161390e565b9699909850959660408101359660609091013595509350505050565b6000806000606084860312156139cf57600080fd5b6139d8846138c8565b95602085013595506040909401359392505050565b600080600080600060a08688031215613a0557600080fd5b613a0e866138c8565b97602087013597506040870135966060810135965060800135945092505050565b6001600160a01b0391909116815260200190565b60008060008060808587031215613a5957600080fd5b613a62856138c8565b966020860135965060408601359560600135945092505050565b60008060008060008060a08789031215613a9557600080fd5b613a9e876138c8565b955060208701356001600160401b03811115613ab957600080fd5b613ac589828a0161390e565b909650945050604087013592506060870135915060808701356001600160401b03811115613af257600080fd5b87016060818a031215613b0457600080fd5b809150509295509295509295565b60008060008060008060c08789031215613b2b57600080fd5b613b34876138c8565b9550613b42602088016138c8565b9450613b50604088016138c8565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008060008060c08789031215613b8a57600080fd5b613b93876138c8565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b600060208284031215613bcd57600080fd5b5035919050565b600080600060608486031215613be957600080fd5b505081359360208301359350604090920135919050565b600080600080600080600060e0888a031215613c1b57600080fd5b613c24886138c8565b9650613c32602089016138c8565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600060a08688031215613c7657600080fd5b613c7f866138c8565b9450613c8d602087016138c8565b94979496505050506040830135926060810135926080909101359150565b60008083601f840112613cbd57600080fd5b5081356001600160401b03811115613cd457600080fd5b6020830191508360208260051b850101111561394f57600080fd5b60008060208385031215613d0257600080fd5b82356001600160401b03811115613d1857600080fd5b613d2485828601613cab565b90969095509350505050565b60005b83811015613d4b578181015183820152602001613d33565b50506000910152565b60008151808452613d6c816020860160208601613d30565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f19858403018852613dba838351613d54565b6020988901989093509190910190600101613d9e565b50909695505050505050565b602081526000613def6020830184613d80565b9392505050565b8015158114613e0457600080fd5b50565b60008060008060808587031215613e1d57600080fd5b613e26856138c8565b93506020850135613e3681613df6565b93969395505050506040820135916060013590565b600080600080600060a08688031215613e6357600080fd5b613e6c866138c8565b9450613e7a602087016138c8565b9350613e88604087016138c8565b94979396509394606081013594506080013592915050565b60008060008060008060008060a0898b031215613ebc57600080fd5b88356001600160401b03811115613ed257600080fd5b613ede8b828c01613cab565b90995097505060208901356001600160401b03811115613efd57600080fd5b613f098b828c01613cab565b90975095505060408901356001600160401b03811115613f2857600080fd5b613f348b828c01613cab565b999c989b509699959896976060870135966080013595509350505050565b600080600080600080600060a0888a031215613f6d57600080fd5b613f76886138c8565b965060208801356001600160401b03811115613f9157600080fd5b613f9d8a828b01613cab565b90975095505060408801356001600160401b03811115613fbc57600080fd5b613fc88a828b01613cab565b989b979a5095989597966060870135966080013595509350505050565b6001600160a01b03929092168252602082015260400190565b6020808252600e908201526d2a24a6a2a627a1a5afa0a226a4a760911b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a06040820152600061407760a083018688614026565b60608301949094525060800152949350505050565b9182526001600160a01b0316602082015260400190565b634e487b7160e01b600052604160045260246000fd5b918252602082015260400190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126140f457600080fd5b83016020810192503590506001600160401b0381111561411357600080fd5b8060051b360382131561394f57600080fd5b81835260208301925060008160005b84811015614163576001600160a01b0361414d836138c8565b1686526020958601959190910190600101614134565b5093949350505050565b60008383855260208501945060208460051b8201018360005b86811015613dd057838303601f19018852600080833536899003601e190181126141ae578283fd5b88016020810192503590506001600160401b038111156141cd57600080fd5b8036038213156141dc57600080fd5b6141e7858284614026565b60209a8b019a90955093909301925050600101614186565b60018060a01b038816815286602082015260c06040820152600061422760c083018789614026565b85606084015284608084015282810360a084015261424584856140dd565b60608352614257606084018284614125565b91505061426760208601866140dd565b838303602085015261427a838284614125565b9250505061428b60408601866140dd565b838303604085015261429e83828461416d565b9d9c50505050505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526023908201527f444154415f53545245414d5f5350524541445f524544554354494f4e5f4641436040820152622a27a960e91b606082015260800190565b60006020828403121561432857600080fd5b5051919050565b6000808335601e1984360301811261434657600080fd5b8301803591506001600160401b0382111561436057600080fd5b60200191503681900382131561394f57600080fd5b8183823760009101908152919050565b81835260006001600160fb1b0383111561439e57600080fd5b8260051b80836020870137939093016020019392505050565b60a0815260006143cb60a083018a8c614125565b82810360208401526143de81898b614385565b905082810360408401526143f381878961416d565b60608401959095525050608001529695505050505050565b60006020828403121561441d57600080fd5b613def826138c8565b60006020828403121561443857600080fd5b8151613def81613df6565b604081526000614457604083018688614125565b828103602084015261446a818587614385565b979650505050505050565b6001600160a01b038316815260406020820181905260009061449990830184613d54565b949350505050565b602081526000613def6020830184613d54565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f1985840301885281518051604085526144f86040860182613d54565b6020928301518682038785015280518083529084019360009350909101905b808310156145425783516001600160a01b031682526020938401936001939093019290910190614517565b5060209a8b019a909550939093019250506001016144d2565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156145d557605f1988860301835283518051604087526145ad6040880182613d54565b6020928301516001600160a01b03169783019790975250938401939290920191600101614587565b50505050602083015184820360208601526145f082826144b4565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f19858403018852815180516040855261463d6040860182613d54565b6020928301518682038785015280518083529084019360009350909101905b8083101561467f578351825260208201915060208401935060018301925061465c565b5060209a8b019a90955093909301925050600101614617565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561470957605f1988860301835283518051604087526146ea6040880182613d54565b60209283015197830197909752509384019392909201916001016146c4565b50505050602083015184820360208601526145f082826145f9565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561470957605f1988860301835283518051604087526147766040880182613d54565b6020928301519783019790975250938401939290920191600101614750565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f1985840301885281518051604085526147d96040860182613d54565b6020928301518682038785015280518083529084019360009350909101905b8083101561481d578351151582526020820191506020840193506001830192506147f8565b5060209a8b019a909550939093019250506001016147b3565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156148a957605f1988860301835283518051604087526148886040880182613d54565b60209283015115159783019790975250938401939290920191600101614862565b50505050602083015184820360208601526145f08282614795565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561470957605f1988860301835283518051604087526149166040880182613d54565b60209283015197830197909752509384019392909201916001016148f0565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f1985840301885281518051604085526149796040860182613d54565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b828110156149d257601f198583030184526149bd828751613d54565b602096870196949094019391506001016149a1565b508097505050505050602082019150602088019750600181019050614953565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015614a7657605f198886030183528351805160408752614a446040880182613d54565b9050602082015191508681036020880152614a5f8183613d54565b965050506020938401939290920191600101614a1e565b50505050602083015184820360208601526145f08282614935565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015614a7657605f198886030183528351805160408752614ae36040880182613d54565b9050602082015191508681036020880152614afe8183613d54565b965050506020938401939290920191600101614abd565b6000815160e08452614b2a60e085018261455b565b905060208301518482036020860152614b438282614698565b91505060408301518482036040860152614b5d8282614724565b91505060608301518482036060860152614b778282614836565b91505060808301518482036080860152614b9182826148c4565b91505060a083015184820360a0860152614bab82826149f2565b91505060c083015184820360c08601526145f08282614a91565b60608152601360608201527229b4b3b730b62832b73234b733a0b1ba34b7b760691b608082015282602082015260a06040820152600061449960a0830184614b15565b604081526000614c1b6040830185613d54565b82810360208401526145f08185614b15565b60018060a01b038716815285602082015260c060408201526000614c5460c0830187613d54565b606083019590955250608081019290925260a0909101529392505050565b600081518084526020840193506020830160005b82811015614163578151865260209586019590910190600101614c86565b60c08082528751908201819052600090602089019060e0840190835b81811015614ce75783516001600160a01b0316835260209384019390920191600101614cc0565b50508381036020850152614cfb818a614c72565b9150508281036040840152614d108188613d80565b60608401969096525050608081019290925260a0909101529392505050565b600060208284031215614d4157600080fd5b81516001600160401b03811115614d5757600080fd5b8201601f81018413614d6857600080fd5b80516001600160401b03811115614d8157614d816140a3565b604051601f8201601f19908116603f011681016001600160401b0381118282101715614daf57614daf6140a3565b604052818152828201602001861015614dc757600080fd5b6145f0826020830160208601613d3056fe5369676e616c5365744d696e436f6e7472696275746f725061796d656e74496e74657276616c5369676e616c5365744d6178546f74616c436f6e7472696275746f72546f6b656e416d6f756e745369676e616c576974686472617746726f6d506f736974696f6e496d70616374506f6f6ca2646970667358221220b4240151186c3ed05c8ef73644455ef7029af8146fe007bfd387e603cd46bc7864736f6c634300081d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101805760003560e01c8063208dd1ff146101855780632a083ca31461019a5780632ab148dd146101b7578063314907c1146101ca57806331847c96146101dd578063392bf7f6146101f05780634a4a7b04146102245780634e2ba52d1461024b5780635588ec5a1461025e578063569936a414610271578063660d0d67146102845780636d00753e146102ab578063781cc3d3146102be57806378b79025146102d15780637ed67107146102e4578063881be502146102f7578063990200cb1461030a5780639ff78c301461031d578063a6a58fab14610344578063ac9650d814610357578063ad4e4ab214610377578063b5256f381461038a578063b97177941461039d578063cd63bfa5146103b0578063cdb07a4f146103c3578063d0b91b01146103d6578063d597d570146103e9578063db477adc146103fc578063e38335e51461040f578063f3388e7514610422578063f373d4b914610449578063feca03a51461045c575b600080fd5b6101986101933660046138e4565b61046f565b005b6101a46206978081565b6040519081526020015b60405180910390f35b6101986101c5366004613956565b61061f565b6101986101d83660046139ba565b610703565b6101986101eb3660046139ed565b610878565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b6040516101ae9190613a2f565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b610198610259366004613a43565b610af7565b61019861026c366004613a7c565b610c22565b61019861027f366004613b12565b610cc7565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b6101986102b9366004613b71565b610ee2565b6101986102cc366004613bbb565b61122e565b6101986102df366004613bd4565b6112b6565b6101986102f2366004613c00565b611490565b6101986103053660046139ba565b611816565b610198610318366004613a43565b611938565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b610198610352366004613c5e565b611a6a565b61036a610365366004613cef565b611c35565b6040516101ae9190613ddc565b610198610385366004613e07565b611d48565b610198610398366004613e4b565b611e93565b6101986103ab366004613a43565b611ff4565b6101986103be3660046139ba565b612127565b6101986103d13660046139ba565b612246565b6101a46103e4366004613ea0565b6123b1565b6101986103f7366004613e07565b61245c565b61019861040a366004613c5e565b6125a7565b61019861041d366004613ea0565b61279d565b6102177f000000000000000000000000000000000000000000000000000000000000000081565b610198610457366004613f52565b612845565b6101a461046a366004613956565b612b3e565b6104ec6040516020016104a79060208082526011908201527054494d454c4f434b5f4d554c544953494760781b604082015260600190565b604051602081830303815290604052805190602001206040518060400160405280601181526020017054494d454c4f434b5f4d554c544953494760781b815250612be2565b60405163208dd1ff60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063208dd1ff9061053a9085908590600401613fe5565b600060405180830381600087803b15801561055457600080fd5b505af1158015610568573d6000803e3d6000fd5b505050506105746137d7565b8051610581906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516105ae9160009086612cfb565b60808101516105be906001612c96565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516105ee9160009085612d58565b61061a6040518060400160405280600a8152602001695265766f6b65526f6c6560b01b81525082612dab565b505050565b61067360405160200161063190613ffe565b604051602081830303815290604052805190602001206040518060400160405280600e81526020016d2a24a6a2a627a1a5afa0a226a4a760911b815250612be2565b60405163134008d360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063134008d3906106ca908890600090899089908990899060040161404f565b600060405180830381600087803b1580156106e457600080fd5b505af11580156106f8573d6000803e3d6000fd5b505050505050505050565b61071560405160200161063190613ffe565b6001600160a01b038316610747578260405163cb9339d560e01b815260040161073e9190613a2f565b60405180910390fd5b6000604051602001610779906020808252600c908201526b2322a2afa922a1a2a4ab22a960a11b604082015260600190565b60405160208183030381529060405280519060200120846040516024016107a192919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905290506107f97f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6108016137d7565b805161080e906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161083b9160009088612cfb565b6108716040518060400160405280601481526020017329b4b3b730b629b2ba2332b2a932b1b2b4bb32b960611b81525082612dab565b5050505050565b61088a60405160200161063190613ffe565b836108aa57846040516318b900b360e21b815260040161073e9190613a2f565b60408051600280825260608201909252600091816020015b60608152602001906001900390816108c25790505090506108e286613040565b856040516024016108f49291906140b9565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b17905281518290600090610931576109316140c7565b6020026020010181905250610945866130be565b846040516024016109579291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110610996576109966140c7565b60200260200101819052506109cd7f0000000000000000000000000000000000000000000000000000000000000000828585613101565b6109d56137d7565b80516109e2906001612c96565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610a0d916000908a612cfb565b6080810151610a1d906001612c96565b60408051808201909152601081526f195919d951185d1854dd1c99585b525960821b60208201526080820151610a569160009089612d58565b6020810151610a66906001612c96565b610ab560006040518060400160405280601b81526020017a656467654461746153747265616d546f6b656e446563696d616c7360281b815250878460200151612d58909392919063ffffffff16565b610aee604051806040016040528060178152602001765369676e616c536574456467654461746153747265616d60481b81525082612dab565b50505050505050565b610b0960405160200161063190613ffe565b6001600160a01b038416610b3057604051634e6e36d560e11b815260040160405180910390fd5b621a5e00831015610b575760405163961b402560e01b81526004810184905260240161073e565b600083604051602401610b6c91815260200190565b60408051601f198184030181529190526020810180516001600160e01b0316630f8c394b60e01b1790529050610ba485828585612f68565b610bac6137d7565b6020810151610bbc906001612c96565b610bf86000604051806040016040528060088152602001671a5b9d195c9d985b60c21b815250878460200151612d58909392919063ffffffff16565b610c1a604051806060016040528060268152602001614dd96026913982612dab565b505050505050565b610c3460405160200161063190613ffe565b60405163d0663e6160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d0663e6190610c8d9089906000908a908a908a908a908a906004016141ff565b600060405180830381600087803b158015610ca757600080fd5b505af1158015610cbb573d6000803e3d6000fd5b50505050505050505050565b610cd960405160200161063190613ffe565b6001600160a01b038616610d0057604051634e6e36d560e11b815260040160405180910390fd5b6001600160a01b038516610d275760405163066f53b160e01b815260040160405180910390fd5b6001600160a01b038416610d4e5760405163d551823d60e01b815260040160405180910390fd5b82600003610d6f576040516301d6f7b160e01b815260040160405180910390fd5b6000858585604051602401610d86939291906142af565b60408051601f198184030181529190526020810180516001600160e01b0316632f1a9acf60e11b1790529050610dbe87828585612f68565b610dc66137d7565b8051610dd3906003612c96565b6040805180820190915260068152651d185c99d95d60d21b60208201528151610dff916000908b612cfb565b6040805180820190915260058152643a37b5b2b760d91b60208201528151610e2a916001908a612cfb565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151610e589160029089612cfb565b6020810151610e68906001612c96565b610ea2600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151612d58909392919063ffffffff16565b610ed8604051806040016040528060148152602001735369676e616c5769746864726177546f6b656e7360601b81525082612dab565b5050505050505050565b610ef460405160200161063190613ffe565b68327cb2734119d3b7a9601e1b831115610f4957604051602001610f17906142d3565b6040516020818303038152906040528051906020012083604051635ebb87c960e01b815260040161073e9291906140b9565b60408051600380825260808201909252600091816020015b6060815260200190600190039081610f61579050509050610f81876132e0565b86604051602401610f939291906140b9565b60408051601f198184030181529190526020810180516001600160e01b03166309d23b6160e31b17905281518290600090610fd057610fd06140c7565b6020026020010181905250610fe487613314565b85604051602401610ff69291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906001908110611035576110356140c7565b602002602001018190525061104987613350565b8460405160240161105b9291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b17905281518290600290811061109a5761109a6140c7565b60200260200101819052506110d17f0000000000000000000000000000000000000000000000000000000000000000828585613101565b6110d96137d7565b80516110e6906001612c96565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611111916000908b612cfb565b6080810151611121906001612c96565b60408051808201909152600681526519995959125960d21b60208201526080820151611150916000908a612d58565b6020810151611160906002612c96565b6111a86000604051806040016040528060148152602001733230ba30a9ba3932b0b6a6bab63a34b83634b2b960611b815250888460200151612d58909392919063ffffffff16565b6111f960016040518060400160405280601f81526020017f6461746153747265616d537072656164526564756374696f6e466163746f7200815250878460200151612d58909392919063ffffffff16565b610ed8604051806040016040528060138152602001725369676e616c5365744461746153747265616d60681b81525082612dab565b61124060405160200161063190613ffe565b60405163c4d252f560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c4d252f590602401600060405180830381600087803b1580156112a257600080fd5b505af1158015610871573d6000803e3d6000fd5b6112c860405160200161063190613ffe565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134a9190614316565b831161136c576040516373586edb60e11b81526004810184905260240161073e565b6206978083111561139357604051633ebd9bc360e21b81526004810184905260240161073e565b6000836040516024016113a891815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166364d6235360e01b17905290506114007f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6114086137d7565b6020810151611418906001612c96565b61145960006040518060400160405280600d81526020016c74696d656c6f636b44656c617960981b815250878460200151612d58909392919063ffffffff16565b61087160405180604001604052806015815260200174496e63726561736554696d656c6f636b44656c617960581b81525082612dab565b6114a260405160200161063190613ffe565b60408051600480825260a08201909252600091816020015b60608152602001906001900390816114ba5790505090506114da88613361565b876040516024016114ec92919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905281518290600090611529576115296140c7565b602002602001018190525061153d88613391565b8660405160240161154f9291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b17905281518290600190811061158e5761158e6140c7565b60200260200101819052506115a2886133cc565b856040516024016115b49291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b1790528151829060029081106115f3576115f36140c7565b60200260200101819052506116078861340f565b846040516024016116199291906140b9565b60408051601f198184030181529190526020810180516001600160e01b0316637152429d60e11b179052815182906003908110611658576116586140c7565b602002602001018190525061168f7f0000000000000000000000000000000000000000000000000000000000000000828585613101565b6116976137d7565b80516116a4906002612c96565b6040805180820190915260058152643a37b5b2b760d91b602082015281516116cf916000908c612cfb565b6040805180820190915260098152681c1c9a58d95199595960ba1b602082015281516116fe916001908b612cfb565b602081015161170e906003612c96565b611755600060405180604001604052806013815260200172383934b1b2a332b2b226bab63a34b83634b2b960691b815250898460200151612d58909392919063ffffffff16565b6117a360016040518060400160405280601a815260200179383934b1b2a332b2b22432b0b93a3132b0ba223ab930ba34b7b760311b815250888460200151612d58909392919063ffffffff16565b6117e260026040518060400160405280600b81526020016a737461626c65507269636560a81b815250878460200151612d58909392919063ffffffff16565b6106f86040518060400160405280601281526020017114da59db985b14d95d141c9a58d95199595960721b81525082612dab565b61182860405160200161063190613ffe565b6001600160a01b038316611851578260405163c1b14c9160e01b815260040161073e9190613a2f565b6000836040516024016118649190613a2f565b60408051601f198184030181529190526020810180516001600160e01b0316630e316ab760e01b17905290506118bc7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6118c46137d7565b80516118d1906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516118fe9160009088612cfb565b6108716040518060400160405280601881526020017729b4b3b730b62932b6b7bb32a7b930b1b632a9b4b3b732b960411b81525082612dab565b61194a60405160200161063190613ffe565b6000848460405160240161195f929190613fe5565b60408051601f198184030181529190526020810180516001600160e01b0316632ac9d0b760e21b17905290506119b77f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6119bf6137d7565b80516119cc906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516119f99160009089612cfb565b6080810151611a09906001612c96565b604080518082019091526007815266726f6c654b657960c81b60208201526080820151611a399160009088612d58565b610c1a6040518060400160405280600f81526020016e5369676e616c4772616e74526f6c6560881b81525082612dab565b611a7c60405160200161063190613ffe565b6001600160a01b038516611aa3576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b038416611aca5760405163d551823d60e01b815260040160405180910390fd5b82600003611aeb57604051630d1bbc9560e01b815260040160405180910390fd5b6000858585604051602401611b02939291906142af565b60408051601f198184030181529190526020810180516001600160e01b0316632bae9a3560e11b1790529050611b5a7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b611b626137d7565b8051611b6f906002612c96565b6040805180820190915260068152651b585c9ad95d60d21b60208201528151611b9b916000908a612cfb565b6040805180820190915260088152673932b1b2b4bb32b960c11b60208201528151611bc99160019089612cfb565b6020810151611bd9906001612c96565b611c13600060405180604001604052806006815260200165185b5bdd5b9d60d21b815250878460200151612d58909392919063ffffffff16565b610aee604051806060016040528060248152602001614e266024913982612dab565b6060816001600160401b03811115611c4f57611c4f6140a3565b604051908082528060200260200182016040528015611c8257816020015b6060815260200190600190039081611c6d5790505b50905060005b82811015611d415760008030868685818110611ca657611ca66140c7565b9050602002810190611cb8919061432f565b604051611cc6929190614375565b600060405180830381855af49150503d8060008114611d01576040519150601f19603f3d011682016040523d82523d6000602084013e611d06565b606091505b509150915081611d1957611d1981613441565b80848481518110611d2c57611d2c6140c7565b60209081029190910101525050600101611c88565b5092915050565b611d5a60405160200161063190613ffe565b6000611d658561347a565b6040516024810191909152841515604482015260640160408051601f198184030181529190526020810180516001600160e01b031663abfdcced60e01b1790529050611dd37f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b611ddb6137d7565b8051611de8906001612c96565b604080518082019091526008815267383937bb34b232b960c11b60208201528151611e169160009089612cfb565b6060810151611e26906001612c96565b60408051808201909152600581526476616c756560d81b60208201526060820151611e5491600090886134b9565b610c1a6040518060400160405280601d81526020017f5369676e616c53657441746f6d69634f7261636c6550726f766964657200000081525082612dab565b611ea560405160200161063190613ffe565b6000611eb1868661350e565b84604051602401611ec392919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b1790529050611f1b7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b611f236137d7565b8051611f30906003612c96565b6040805180820190915260068152656f7261636c6560d01b60208201528151611f5c916000908a612cfb565b6040805180820190915260058152643a37b5b2b760d91b60208201528151611f879160019089612cfb565b604080518082019091526008815267383937bb34b232b960c11b60208201528151611fb59160029088612cfb565b610aee6040518060400160405280601f81526020017f5369676e616c5365744f7261636c6550726f7669646572466f72546f6b656e0081525082612dab565b61200660405160200161063190613ffe565b6000848460405160240161201b929190613fe5565b60408051601f198184030181529190526020810180516001600160e01b031663208dd1ff60e01b17905290506120737f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b61207b6137d7565b8051612088906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516120b59160009089612cfb565b60808101516120c5906001612c96565b604080518082019091526007815266726f6c654b657960c81b602082015260808201516120f59160009088612d58565b610c1a6040518060400160405280601081526020016f5369676e616c5265766f6b65526f6c6560801b81525082612dab565b61213960405160200161063190613ffe565b6001600160a01b038316612162578260405163c1b14c9160e01b815260040161073e9190613a2f565b6000836040516024016121759190613a2f565b60408051601f198184030181529190526020810180516001600160e01b03166375896b0f60e11b17905290506121cd7f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6121d56137d7565b80516121e2906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b6020820152815161220f9160009088612cfb565b6108716040518060400160405280601581526020017429b4b3b730b620b23227b930b1b632a9b4b3b732b960591b81525082612dab565b61225860405160200161063190613ffe565b6001600160a01b0383166122815782604051630f773b1f60e31b815260040161073e9190613a2f565b60006040516020016122b6906020808252600f908201526e484f4c44494e475f4144445245535360881b604082015260600190565b60405160208183030381529060405280519060200120846040516024016122de92919061408c565b60408051601f198184030181529190526020810180516001600160e01b031663ca446dd960e01b17905290506123367f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b61233e6137d7565b805161234b906001612c96565b6040805180820190915260078152661858d8dbdd5b9d60ca1b602082015281516123789160009088612cfb565b610871604051806040016040528060178152602001765369676e616c536574486f6c64696e674164647265737360481b81525082612dab565b60405163b1c5f42760e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b1c5f4279061240e908c908c908a908a908e908e908c908c906004016143b7565b602060405180830381865afa15801561242b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244f9190614316565b9998505050505050505050565b61246e60405160200161063190613ffe565b6000612479856135a3565b6040516024810191909152841515604482015260640160408051601f198184030181529190526020810180516001600160e01b031663abfdcced60e01b17905290506124e77f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b6124ef6137d7565b80516124fc906001612c96565b604080518082019091526008815267383937bb34b232b960c11b6020820152815161252a9160009089612cfb565b606081015161253a906001612c96565b60408051808201909152600581526476616c756560d81b6020820152606082015161256891600090886134b9565b610c1a6040518060400160405280601e81526020017f5369676e616c5365744f7261636c6550726f7669646572456e61626c6564000081525082612dab565b6125b960405160200161063190613ffe565b6001600160a01b0385166125e0576040516302fde0d760e11b815260040160405180910390fd5b6001600160a01b03841661260757604051639ab5d12760e01b815260040160405180910390fd5b826000036126285760405163b3d3553960e01b815260040160405180910390fd5b600085858560405160240161263f939291906142af565b60408051601f198184030181529190526020810180516001600160e01b031663f128024b60e01b17905290506126977f0000000000000000000000000000000000000000000000000000000000000000828585612f68565b61269f6137d7565b80516126ac906002612c96565b6040805180820190915260068152651b585c9ad95d60d21b602082015281516126d8916000908a612cfb565b60408051808201909152600e81526d199d5b991a5b99d058d8dbdd5b9d60921b6020820152815161270c9160019089612cfb565b602081015161271c906001612c96565b61275f60006040518060400160405280600f81526020016e1c99591d58dd1a5bdb905b5bdd5b9d608a1b815250878460200151612d58909392919063ffffffff16565b610aee6040518060400160405280601c81526020017b14da59db985b1499591d58d953195b9d125b5c1858dd105b5bdd5b9d60221b81525082612dab565b6127af60405160200161063190613ffe565b60405163e38335e560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e38335e590612809908b908b908b908b908b908b908b908b906004016143b7565b600060405180830381600087803b15801561282357600080fd5b505af1158015612837573d6000803e3d6000fd5b505050505050505050505050565b61285760405160200161063190613ffe565b6001600160a01b03871661287e57604051634e6e36d560e11b815260040160405180910390fd5b8483146128a257604051630a6a4f7160e21b815261073e90869085906004016140b9565b60005b858110156129de5760008787838181106128c1576128c16140c7565b90506020020160208101906128d6919061440b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c769d1a16040516020016129419060208082526016908201527510d3d395149250955513d497d513d2d15397d31254d560521b604082015260600190565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b815260040161297592919061408c565b602060405180830381865afa158015612992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b69190614426565b6129d55780604051634a59130960e01b815260040161073e9190613a2f565b506001016128a5565b506000868686866040516024016129f89493929190614443565b60408051601f198184030181529190526020810180516001600160e01b031663127db19160e21b1790529050612a3088828585612f68565b612a386137d7565b8051612a459060016135e3565b612aa7600060405180604001604052806006815260200165746f6b656e7360d01b8152508a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050865194939291505061364d565b6020810151612ab79060016135e3565b612b1c600060405180604001604052806007815260200166616d6f756e747360c81b815250888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505050602085015192919061364d565b6106f8604051806060016040528060278152602001614dff6027913982612dab565b604051638065657f60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638065657f90612b9790899085908a908a908a908a9060040161404f565b602060405180830381865afa158015612bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd89190614316565b9695505050505050565b60405163ac4ab3fb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac4ab3fb90612c309033908690600401613fe5565b602060405180830381865afa158015612c4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c719190614426565b612c9257338160405163a35b150b60e01b815260040161073e929190614475565b5050565b806001600160401b03811115612cae57612cae6140a3565b604051908082528060200260200182016040528015612cf457816020015b604080518082019091526060815260006020820152815260200190600190039081612ccc5790505b5090915250565b8184600001518481518110612d1257612d126140c7565b6020026020010151600001819052508084600001518481518110612d3857612d386140c7565b6020908102919091018101516001600160a01b0390921691015250505050565b8184600001518481518110612d6f57612d6f6140c7565b6020026020010151600001819052508084600001518481518110612d9557612d956140c7565b6020026020010151602001818152505050505050565b612db36137d7565b600083604051602001612dc691906144a1565b604051602081830303815290604052805190602001209050612df660018360800151612c9690919063ffffffff16565b604080518082019091526009815268616374696f6e4b657960b81b60208201526080830151612e289160009084612d58565b60c0820151612e3890600161369f565b60408051808201909152600b81526a1858dd1a5bdb931858995b60aa1b602082015260c0830151612e6c9160009087613701565b604051630937807960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906324de01e490612eba9084908690600401614bc5565b600060405180830381600087803b158015612ed457600080fd5b505af1158015612ee8573d6000803e3d6000fd5b505060405163483624fb60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063906c49f69150612f3a9087908790600401614c08565b600060405180830381600087803b158015612f5457600080fd5b505af1158015610ed8573d6000803e3d6000fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166301d5062a8560008686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614316565b6040518763ffffffff1660e01b8152600401612f3a96959493929190614c2d565b600060405160200161307990602080825260139082015272115111d157d110551057d4d51491505357d251606a1b604082015260600190565b60405160208183030381529060405280519060200120826040516020016130a192919061408c565b604051602081830303815290604052805190602001209050919050565b6000604051602001613079906020808252601f908201527f454447455f444154415f53545245414d5f544f4b454e5f444543494d414c5300604082015260600190565b82516000816001600160401b0381111561311d5761311d6140a3565b604051908082528060200260200182016040528015613146578160200160208202803683370190505b50905060005b828110156131875786828281518110613167576131676140c7565b6001600160a01b039092166020928302919091019091015260010161314c565b506000826001600160401b038111156131a2576131a26140a3565b6040519080825280602002602001820160405280156131cb578160200160208202803683370190505b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638f2a0bb083838989897f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f27a0c926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613260573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132849190614316565b6040518763ffffffff1660e01b81526004016132a596959493929190614ca4565b600060405180830381600087803b1580156132bf57600080fd5b505af11580156132d3573d6000803e3d6000fd5b5050505050505050505050565b6000604051602001613079906020808252600e908201526d1110551057d4d51491505357d25160921b604082015260600190565b6000604051602001613079906020808252601690820152752220aa20afa9aa2922a0a6afa6aaa62a24a82624a2a960511b604082015260600190565b6000604051602001613079906142d3565b6000604051602001613079906020808252600a908201526914149250d157d191515160b21b604082015260600190565b600060405160200161307990602080825260159082015274282924a1a2afa322a2a22fa6aaa62a24a82624a2a960591b604082015260600190565b6000604051602001613079906020808252601d908201527f50524943455f464545445f4845415254424541545f4455524154494f4e000000604082015260600190565b6000604051602001613079906020808252600c908201526b535441424c455f505249434560a01b604082015260600190565b60008061344d8361373e565b915091508015613471578160405162461bcd60e51b815260040161073e91906144a1565b61061a836137ce565b60006040516020016130799060208082526019908201527824a9afa0aa27a6a4a1afa7a920a1a622afa82927ab24a222a960391b604082015260600190565b81846000015184815181106134d0576134d06140c7565b60200260200101516000018190525080846000015184815181106134f6576134f66140c7565b60209081029190910181015191151591015250505050565b600060405160200161354d9060208082526019908201527827a920a1a622afa82927ab24a222a92fa327a92faa27a5a2a760391b604082015260600190565b60408051601f198184030181528282528051602091820120908301526001600160a01b03808616918301919091528316606082015260800160405160208183030381529060405280519060200120905092915050565b6000604051602001613079906020808252601a90820152791254d7d3d49050d31157d41493d59251115497d153905093115160321b604082015260600190565b806001600160401b038111156135fb576135fb6140a3565b60405190808252806020026020018201604052801561364057816020015b60408051808201909152606080825260208201528152602001906001900390816136195790505b5082602001819052505050565b8184602001518481518110613664576136646140c7565b602002602001015160000181905250808460200151848151811061368a5761368a6140c7565b60200260200101516020018190525050505050565b806001600160401b038111156136b7576136b76140a3565b604051908082528060200260200182016040528015612cf457816020015b60408051808201909152606080825260208201528152602001906001900390816136d557505090915250565b8184600001518481518110613718576137186140c7565b602002602001015160000181905250808460000151848151811061368a5761368a6140c7565b60606000604483511015613765575050604080516020810190915260008082529092909150565b6000613772846020015190565b90506307b9e43360e51b6001600160e01b03198216016137b157600484019350838060200190518101906137a69190614d2f565b946001945092505050565b600060405180602001604052806000815250909250925050915091565b80518060208301fd5b604080516101208101909152606060e0820181815261010083019190915281908152602001613819604051806040016040528060608152602001606081525090565b815260200161383b604051806040016040528060608152602001606081525090565b815260200161385d604051806040016040528060608152602001606081525090565b815260200161387f604051806040016040528060608152602001606081525090565b81526020016138a1604051806040016040528060608152602001606081525090565b81526020016138c3604051806040016040528060608152602001606081525090565b905290565b80356001600160a01b03811681146138df57600080fd5b919050565b600080604083850312156138f757600080fd5b613900836138c8565b946020939093013593505050565b60008083601f84011261392057600080fd5b5081356001600160401b0381111561393757600080fd5b60208301915083602082850101111561394f57600080fd5b9250929050565b60008060008060006080868803121561396e57600080fd5b613977866138c8565b945060208601356001600160401b0381111561399257600080fd5b61399e8882890161390e565b9699909850959660408101359660609091013595509350505050565b6000806000606084860312156139cf57600080fd5b6139d8846138c8565b95602085013595506040909401359392505050565b600080600080600060a08688031215613a0557600080fd5b613a0e866138c8565b97602087013597506040870135966060810135965060800135945092505050565b6001600160a01b0391909116815260200190565b60008060008060808587031215613a5957600080fd5b613a62856138c8565b966020860135965060408601359560600135945092505050565b60008060008060008060a08789031215613a9557600080fd5b613a9e876138c8565b955060208701356001600160401b03811115613ab957600080fd5b613ac589828a0161390e565b909650945050604087013592506060870135915060808701356001600160401b03811115613af257600080fd5b87016060818a031215613b0457600080fd5b809150509295509295509295565b60008060008060008060c08789031215613b2b57600080fd5b613b34876138c8565b9550613b42602088016138c8565b9450613b50604088016138c8565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008060008060c08789031215613b8a57600080fd5b613b93876138c8565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b600060208284031215613bcd57600080fd5b5035919050565b600080600060608486031215613be957600080fd5b505081359360208301359350604090920135919050565b600080600080600080600060e0888a031215613c1b57600080fd5b613c24886138c8565b9650613c32602089016138c8565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600060a08688031215613c7657600080fd5b613c7f866138c8565b9450613c8d602087016138c8565b94979496505050506040830135926060810135926080909101359150565b60008083601f840112613cbd57600080fd5b5081356001600160401b03811115613cd457600080fd5b6020830191508360208260051b850101111561394f57600080fd5b60008060208385031215613d0257600080fd5b82356001600160401b03811115613d1857600080fd5b613d2485828601613cab565b90969095509350505050565b60005b83811015613d4b578181015183820152602001613d33565b50506000910152565b60008151808452613d6c816020860160208601613d30565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f19858403018852613dba838351613d54565b6020988901989093509190910190600101613d9e565b50909695505050505050565b602081526000613def6020830184613d80565b9392505050565b8015158114613e0457600080fd5b50565b60008060008060808587031215613e1d57600080fd5b613e26856138c8565b93506020850135613e3681613df6565b93969395505050506040820135916060013590565b600080600080600060a08688031215613e6357600080fd5b613e6c866138c8565b9450613e7a602087016138c8565b9350613e88604087016138c8565b94979396509394606081013594506080013592915050565b60008060008060008060008060a0898b031215613ebc57600080fd5b88356001600160401b03811115613ed257600080fd5b613ede8b828c01613cab565b90995097505060208901356001600160401b03811115613efd57600080fd5b613f098b828c01613cab565b90975095505060408901356001600160401b03811115613f2857600080fd5b613f348b828c01613cab565b999c989b509699959896976060870135966080013595509350505050565b600080600080600080600060a0888a031215613f6d57600080fd5b613f76886138c8565b965060208801356001600160401b03811115613f9157600080fd5b613f9d8a828b01613cab565b90975095505060408801356001600160401b03811115613fbc57600080fd5b613fc88a828b01613cab565b989b979a5095989597966060870135966080013595509350505050565b6001600160a01b03929092168252602082015260400190565b6020808252600e908201526d2a24a6a2a627a1a5afa0a226a4a760911b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a06040820152600061407760a083018688614026565b60608301949094525060800152949350505050565b9182526001600160a01b0316602082015260400190565b634e487b7160e01b600052604160045260246000fd5b918252602082015260400190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126140f457600080fd5b83016020810192503590506001600160401b0381111561411357600080fd5b8060051b360382131561394f57600080fd5b81835260208301925060008160005b84811015614163576001600160a01b0361414d836138c8565b1686526020958601959190910190600101614134565b5093949350505050565b60008383855260208501945060208460051b8201018360005b86811015613dd057838303601f19018852600080833536899003601e190181126141ae578283fd5b88016020810192503590506001600160401b038111156141cd57600080fd5b8036038213156141dc57600080fd5b6141e7858284614026565b60209a8b019a90955093909301925050600101614186565b60018060a01b038816815286602082015260c06040820152600061422760c083018789614026565b85606084015284608084015282810360a084015261424584856140dd565b60608352614257606084018284614125565b91505061426760208601866140dd565b838303602085015261427a838284614125565b9250505061428b60408601866140dd565b838303604085015261429e83828461416d565b9d9c50505050505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526023908201527f444154415f53545245414d5f5350524541445f524544554354494f4e5f4641436040820152622a27a960e91b606082015260800190565b60006020828403121561432857600080fd5b5051919050565b6000808335601e1984360301811261434657600080fd5b8301803591506001600160401b0382111561436057600080fd5b60200191503681900382131561394f57600080fd5b8183823760009101908152919050565b81835260006001600160fb1b0383111561439e57600080fd5b8260051b80836020870137939093016020019392505050565b60a0815260006143cb60a083018a8c614125565b82810360208401526143de81898b614385565b905082810360408401526143f381878961416d565b60608401959095525050608001529695505050505050565b60006020828403121561441d57600080fd5b613def826138c8565b60006020828403121561443857600080fd5b8151613def81613df6565b604081526000614457604083018688614125565b828103602084015261446a818587614385565b979650505050505050565b6001600160a01b038316815260406020820181905260009061449990830184613d54565b949350505050565b602081526000613def6020830184613d54565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f1985840301885281518051604085526144f86040860182613d54565b6020928301518682038785015280518083529084019360009350909101905b808310156145425783516001600160a01b031682526020938401936001939093019290910190614517565b5060209a8b019a909550939093019250506001016144d2565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156145d557605f1988860301835283518051604087526145ad6040880182613d54565b6020928301516001600160a01b03169783019790975250938401939290920191600101614587565b50505050602083015184820360208601526145f082826144b4565b95945050505050565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f19858403018852815180516040855261463d6040860182613d54565b6020928301518682038785015280518083529084019360009350909101905b8083101561467f578351825260208201915060208401935060018301925061465c565b5060209a8b019a90955093909301925050600101614617565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561470957605f1988860301835283518051604087526146ea6040880182613d54565b60209283015197830197909752509384019392909201916001016146c4565b50505050602083015184820360208601526145f082826145f9565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561470957605f1988860301835283518051604087526147766040880182613d54565b6020928301519783019790975250938401939290920191600101614750565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f1985840301885281518051604085526147d96040860182613d54565b6020928301518682038785015280518083529084019360009350909101905b8083101561481d578351151582526020820191506020840193506001830192506147f8565b5060209a8b019a909550939093019250506001016147b3565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b818110156148a957605f1988860301835283518051604087526148886040880182613d54565b60209283015115159783019790975250938401939290920191600101614862565b50505050602083015184820360208601526145f08282614795565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b8181101561470957605f1988860301835283518051604087526149166040880182613d54565b60209283015197830197909752509384019392909201916001016148f0565b600082825180855260208501945060208160051b8301016020850160005b83811015613dd057601f1985840301885281518051604085526149796040860182613d54565b6020928301518682038785015280518083529084019391925081830191600582901b84010160005b828110156149d257601f198583030184526149bd828751613d54565b602096870196949094019391506001016149a1565b508097505050505050602082019150602088019750600181019050614953565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015614a7657605f198886030183528351805160408752614a446040880182613d54565b9050602082015191508681036020880152614a5f8183613d54565b965050506020938401939290920191600101614a1e565b50505050602083015184820360208601526145f08282614935565b60006040830182516040855281815180845260608701915060608160051b880101935060208301925060005b81811015614a7657605f198886030183528351805160408752614ae36040880182613d54565b9050602082015191508681036020880152614afe8183613d54565b965050506020938401939290920191600101614abd565b6000815160e08452614b2a60e085018261455b565b905060208301518482036020860152614b438282614698565b91505060408301518482036040860152614b5d8282614724565b91505060608301518482036060860152614b778282614836565b91505060808301518482036080860152614b9182826148c4565b91505060a083015184820360a0860152614bab82826149f2565b91505060c083015184820360c08601526145f08282614a91565b60608152601360608201527229b4b3b730b62832b73234b733a0b1ba34b7b760691b608082015282602082015260a06040820152600061449960a0830184614b15565b604081526000614c1b6040830185613d54565b82810360208401526145f08185614b15565b60018060a01b038716815285602082015260c060408201526000614c5460c0830187613d54565b606083019590955250608081019290925260a0909101529392505050565b600081518084526020840193506020830160005b82811015614163578151865260209586019590910190600101614c86565b60c08082528751908201819052600090602089019060e0840190835b81811015614ce75783516001600160a01b0316835260209384019390920191600101614cc0565b50508381036020850152614cfb818a614c72565b9150508281036040840152614d108188613d80565b60608401969096525050608081019290925260a0909101529392505050565b600060208284031215614d4157600080fd5b81516001600160401b03811115614d5757600080fd5b8201601f81018413614d6857600080fd5b80516001600160401b03811115614d8157614d816140a3565b604051601f8201601f19908116603f011681016001600160401b0381118282101715614daf57614daf6140a3565b604052818152828201602001861015614dc757600080fd5b6145f0826020830160208601613d3056fe5369676e616c5365744d696e436f6e7472696275746f725061796d656e74496e74657276616c5369676e616c5365744d6178546f74616c436f6e7472696275746f72546f6b656e416d6f756e745369676e616c576974686472617746726f6d506f736974696f6e496d70616374506f6f6ca2646970667358221220b4240151186c3ed05c8ef73644455ef7029af8146fe007bfd387e603cd46bc7864736f6c634300081d0033", "libraries": { - "MarketUtils": "0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96" + "MarketUtils": "0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB" }, "devdoc": { "kind": "dev", diff --git a/deployments/arbitrum/solcInputs/02b1f859efc9c56ded8960da79621723.json b/deployments/arbitrum/solcInputs/02b1f859efc9c56ded8960da79621723.json new file mode 100644 index 000000000..5548ee3c9 --- /dev/null +++ b/deployments/arbitrum/solcInputs/02b1f859efc9c56ded8960da79621723.json @@ -0,0 +1,1149 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorInterface {\n function latestAnswer() external view returns (int256);\n\n function latestTimestamp() external view returns (uint256);\n\n function latestRound() external view returns (uint256);\n\n function getAnswer(uint256 roundId) external view returns (int256);\n\n function getTimestamp(uint256 roundId) external view returns (uint256);\n\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\n\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\n}\n" + }, + "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {AggregatorInterface} from \"./AggregatorInterface.sol\";\nimport {AggregatorV3Interface} from \"./AggregatorV3Interface.sol\";\n\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\n" + }, + "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(\n uint80 _roundId\n ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function latestRoundData()\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}\n" + }, + "@gelatonetwork/relay-context/contracts/base/GelatoRelayBase.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.1;\n\nimport {\n GelatoRelayContractsUtils\n} from \"../utils/GelatoRelayContractsUtils.sol\";\n\nabstract contract GelatoRelayBase is GelatoRelayContractsUtils {\n modifier onlyGelatoRelay() {\n require(_isGelatoRelay(msg.sender), \"onlyGelatoRelay\");\n _;\n }\n\n function _isGelatoRelay(address _forwarder) internal view returns (bool) {\n if (_forwarder == _gelatoRelay) {\n return true;\n }\n return false;\n }\n}\n" + }, + "@gelatonetwork/relay-context/contracts/constants/GelatoRelay.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.1;\n\naddress constant GELATO_RELAY_V1 = 0xaBcC9b596420A9E9172FD5938620E265a0f9Df92;\naddress constant GELATO_RELAY_ERC2771_V1 = 0xb539068872230f20456CF38EC52EF2f91AF4AE49;\naddress constant GELATO_RELAY_CONCURRENT_ERC2771_V1 = 0x8598806401A63Ddf52473F1B3C55bC9E33e2d73b;\n\naddress constant GELATO_RELAY_V2 = 0xcd565435e0d2109feFde337a66491541Df0D1420;\naddress constant GELATO_RELAY_ERC2771_V2 = 0x8aCE64CEA52b409F930f60B516F65197faD4B056;\naddress constant GELATO_RELAY_CONCURRENT_ERC2771_V2 = 0xc7739c195618D314C08E8626C98f8573E4E43634;\n\naddress constant GELATO_RELAY_ZKSYNC_V1 = 0xB16a1DbE755f992636705fDbb3A8678a657EB3ea;\naddress constant GELATO_RELAY_ERC2771_ZKSYNC_V1 = 0x22DCC39b2AC376862183dd35A1664798dafC7Da6;\n// solhint-disable-next-line max-line-length\naddress constant GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC_V1 = 0xBa4082F4961c8Fb76231995C967CD9aa40f321b5;\n\naddress constant GELATO_RELAY_ZKSYNC_V2 = 0x42120A1417a091a52A8d4590E28fc6C0F61E5632;\naddress constant GELATO_RELAY_ERC2771_ZKSYNC_V2 = 0xACeD988c5B5Fe3f11848c728D9a5f66Cf34c9e73;\n// solhint-disable-next-line max-line-length\naddress constant GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC_V2 = 0xbbCe89ACdD86D0130BDc3f1fe37C3aEDd79fc1F4;\n\naddress constant GELATO_RELAY_BOTANIX_V2 = 0x61aCe8fBA7B80AEf8ED67f37CB60bE00180872aD;\naddress constant GELATO_RELAY_ERC2771_BOTANIX_V2 = 0x368165B2AFb95FaE8ceC409Efa59d5091f9875A5;\n// solhint-disable-next-line max-line-length\naddress constant GELATO_RELAY_CONCURRENT_ERC2771_BOTANIX_V2 = 0x038479687b7bC7943313bFfd524A4aCc96B3F9BE;\n" + }, + "@gelatonetwork/relay-context/contracts/constants/Tokens.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.1;\n\naddress constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n" + }, + "@gelatonetwork/relay-context/contracts/GelatoRelayContext.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.1;\n\nimport {GelatoRelayBase} from \"./base/GelatoRelayBase.sol\";\nimport {TokenUtils} from \"./lib/TokenUtils.sol\";\n\nuint256 constant _FEE_COLLECTOR_START = 72; // offset: address + address + uint256\nuint256 constant _FEE_TOKEN_START = 52; // offset: address + uint256\nuint256 constant _FEE_START = 32; // offset: uint256\n\n// WARNING: Do not use this free fn by itself, always inherit GelatoRelayContext\n// solhint-disable-next-line func-visibility, private-vars-leading-underscore\nfunction _getFeeCollectorRelayContext() pure returns (address feeCollector) {\n assembly {\n feeCollector := shr(\n 96,\n calldataload(sub(calldatasize(), _FEE_COLLECTOR_START))\n )\n }\n}\n\n// WARNING: Do not use this free fn by itself, always inherit GelatoRelayContext\n// solhint-disable-next-line func-visibility, private-vars-leading-underscore\nfunction _getFeeTokenRelayContext() pure returns (address feeToken) {\n assembly {\n feeToken := shr(96, calldataload(sub(calldatasize(), _FEE_TOKEN_START)))\n }\n}\n\n// WARNING: Do not use this free fn by itself, always inherit GelatoRelayContext\n// solhint-disable-next-line func-visibility, private-vars-leading-underscore\nfunction _getFeeRelayContext() pure returns (uint256 fee) {\n assembly {\n fee := calldataload(sub(calldatasize(), _FEE_START))\n }\n}\n\n/**\n * @dev Context variant with feeCollector, feeToken and fee appended to msg.data\n * Expects calldata encoding:\n * abi.encodePacked( _data,\n * _feeCollector,\n * _feeToken,\n * _fee);\n * Therefore, we're expecting 20 + 20 + 32 = 72 bytes to be appended to normal msgData\n * 32bytes start offsets from calldatasize:\n * feeCollector: - 72 bytes\n * feeToken: - 52 bytes\n * fee: - 32 bytes\n */\n/// @dev Do not use with GelatoRelayFeeCollector - pick only one\nabstract contract GelatoRelayContext is GelatoRelayBase {\n using TokenUtils for address;\n\n // DANGER! Only use with onlyGelatoRelay `_isGelatoRelay` before transferring\n function _transferRelayFee() internal {\n _getFeeToken().transfer(_getFeeCollector(), _getFee());\n }\n\n // DANGER! Only use with onlyGelatoRelay `_isGelatoRelay` before transferring\n function _transferRelayFeeCapped(uint256 _maxFee) internal {\n uint256 fee = _getFee();\n require(\n fee <= _maxFee,\n \"GelatoRelayContext._transferRelayFeeCapped: maxFee\"\n );\n _getFeeToken().transfer(_getFeeCollector(), fee);\n }\n\n function _getMsgData() internal view returns (bytes calldata) {\n return\n _isGelatoRelay(msg.sender)\n ? msg.data[:msg.data.length - _FEE_COLLECTOR_START]\n : msg.data;\n }\n\n // Only use with GelatoRelayBase onlyGelatoRelay or `_isGelatoRelay` checks\n function _getFeeCollector() internal pure returns (address) {\n return _getFeeCollectorRelayContext();\n }\n\n // Only use with previous onlyGelatoRelay or `_isGelatoRelay` checks\n function _getFeeToken() internal pure returns (address) {\n return _getFeeTokenRelayContext();\n }\n\n // Only use with previous onlyGelatoRelay or `_isGelatoRelay` checks\n function _getFee() internal pure returns (uint256) {\n return _getFeeRelayContext();\n }\n}\n" + }, + "@gelatonetwork/relay-context/contracts/lib/TokenUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.1;\n\nimport {NATIVE_TOKEN} from \"../constants/Tokens.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {\n IERC20Permit\n} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\nimport {\n SafeERC20\n} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nlibrary TokenUtils {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n\n modifier onlyERC20(address _token) {\n require(_token != NATIVE_TOKEN, \"TokenUtils.onlyERC20\");\n _;\n }\n\n function permit(\n address _token,\n address _owner,\n address _spender,\n uint256 _value,\n uint256 _deadline,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) internal onlyERC20(_token) {\n IERC20Permit(_token).safePermit(\n _owner,\n _spender,\n _value,\n _deadline,\n _v,\n _r,\n _s\n );\n }\n\n function transfer(\n address _token,\n address _to,\n uint256 _amount\n ) internal {\n if (_amount == 0) return;\n _token == NATIVE_TOKEN\n ? Address.sendValue(payable(_to), _amount)\n : IERC20(_token).safeTransfer(_to, _amount);\n }\n\n function transferFrom(\n address _token,\n address _from,\n address _to,\n uint256 _amount\n ) internal onlyERC20(_token) {\n if (_amount == 0) return;\n IERC20(_token).safeTransferFrom(_from, _to, _amount);\n }\n\n function getBalance(address token, address user)\n internal\n view\n returns (uint256)\n {\n return\n token == NATIVE_TOKEN\n ? user.balance\n : IERC20(token).balanceOf(user);\n }\n}\n" + }, + "@gelatonetwork/relay-context/contracts/utils/GelatoRelayContractsUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.1;\n\nimport {\n GELATO_RELAY_V1,\n GELATO_RELAY_V2,\n GELATO_RELAY_BOTANIX_V2,\n GELATO_RELAY_ZKSYNC_V1,\n GELATO_RELAY_ZKSYNC_V2,\n GELATO_RELAY_ERC2771_V1,\n GELATO_RELAY_CONCURRENT_ERC2771_V1,\n GELATO_RELAY_ERC2771_V2,\n GELATO_RELAY_CONCURRENT_ERC2771_V2,\n GELATO_RELAY_ERC2771_ZKSYNC_V1,\n GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC_V1,\n GELATO_RELAY_ERC2771_ZKSYNC_V2,\n GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC_V2,\n GELATO_RELAY_ERC2771_BOTANIX_V2,\n GELATO_RELAY_CONCURRENT_ERC2771_BOTANIX_V2\n} from \"../constants/GelatoRelay.sol\";\n\nabstract contract GelatoRelayContractsUtils {\n address internal immutable _gelatoRelay;\n address internal immutable _gelatoRelayERC2771;\n address internal immutable _gelatoRelayConcurrentERC2771;\n\n constructor() {\n (\n _gelatoRelay,\n _gelatoRelayERC2771,\n _gelatoRelayConcurrentERC2771\n ) = _getRelayAddresses();\n }\n\n function _getRelayAddresses()\n internal\n view\n returns (\n address,\n address,\n address\n )\n {\n if (_isBotanixChainId(block.chainid)) {\n return (\n GELATO_RELAY_BOTANIX_V2,\n GELATO_RELAY_ERC2771_BOTANIX_V2,\n GELATO_RELAY_CONCURRENT_ERC2771_BOTANIX_V2\n );\n } else if (_isV1ZkSyncChainId(block.chainid)) {\n return (\n GELATO_RELAY_ZKSYNC_V1,\n GELATO_RELAY_ERC2771_ZKSYNC_V1,\n GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC_V1\n );\n } else if (_isV2ZkSyncChainId(block.chainid)) {\n return (\n GELATO_RELAY_ZKSYNC_V2,\n GELATO_RELAY_ERC2771_ZKSYNC_V2,\n GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC_V2\n );\n } else if (_isV1ChainId(block.chainid)) {\n return (\n GELATO_RELAY_V1,\n GELATO_RELAY_ERC2771_V1,\n GELATO_RELAY_CONCURRENT_ERC2771_V1\n );\n } else {\n return (\n GELATO_RELAY_V2,\n GELATO_RELAY_ERC2771_V2,\n GELATO_RELAY_CONCURRENT_ERC2771_V2\n );\n }\n }\n\n // solhint-disable-next-line function-max-lines\n function _isV1ChainId(uint256 chainId) private pure returns (bool) {\n if (\n chainId == 1 ||\n chainId == 10 ||\n chainId == 25 ||\n chainId == 30 ||\n chainId == 56 ||\n chainId == 100 ||\n chainId == 109 ||\n chainId == 137 ||\n chainId == 183 ||\n chainId == 233 ||\n chainId == 250 ||\n chainId == 314 ||\n chainId == 1088 ||\n chainId == 1101 ||\n chainId == 1135 ||\n chainId == 1284 ||\n chainId == 1285 ||\n chainId == 1729 ||\n chainId == 1829 ||\n chainId == 1833 ||\n chainId == 2039 ||\n chainId == 3776 ||\n chainId == 4202 ||\n chainId == 6398 ||\n chainId == 8453 ||\n chainId == 10200 ||\n chainId == 18231 ||\n chainId == 18233 ||\n chainId == 25327 ||\n chainId == 34443 ||\n chainId == 41455 ||\n chainId == 42069 ||\n chainId == 42161 ||\n chainId == 43114 ||\n chainId == 59144 ||\n chainId == 80002 ||\n chainId == 80084 ||\n chainId == 81457 ||\n chainId == 84532 ||\n chainId == 111188 ||\n chainId == 241120 ||\n chainId == 421614 ||\n chainId == 656476 ||\n chainId == 1261120 ||\n chainId == 6038361 ||\n chainId == 7777777 ||\n chainId == 11155111 ||\n chainId == 11155420 ||\n chainId == 29313331 ||\n chainId == 69658185 ||\n chainId == 89346162 ||\n chainId == 94204209 ||\n chainId == 123420111 ||\n chainId == 168587773 ||\n chainId == 222000222 ||\n chainId == 994873017 ||\n chainId == 1380012617 ||\n chainId == 3155399334 ||\n chainId == 80998896642 ||\n chainId == 88153591557\n ) {\n return true;\n } else {\n return false;\n }\n }\n\n function _isV1ZkSyncChainId(uint256 chainId) private pure returns (bool) {\n if (chainId == 324 || chainId == 280) {\n return true;\n }\n return false;\n }\n\n function _isV2ZkSyncChainId(uint256 chainId) private pure returns (bool) {\n if (chainId == 11124 || chainId == 2741) {\n return true;\n }\n return false;\n }\n\n function _isBotanixChainId(uint256 chainId) private pure returns (bool) {\n if (chainId == 3637 || chainId == 3636) {\n return true;\n }\n return false;\n }\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IExecutor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\n\nimport { IWorker } from \"./IWorker.sol\";\nimport { ILayerZeroExecutor } from \"./ILayerZeroExecutor.sol\";\nimport { ILayerZeroReadExecutor } from \"./ILayerZeroReadExecutor.sol\";\n\ninterface IExecutor is IWorker, ILayerZeroExecutor, ILayerZeroReadExecutor {\n struct DstConfigParam {\n uint32 dstEid;\n uint64 lzReceiveBaseGas;\n uint64 lzComposeBaseGas;\n uint16 multiplierBps;\n uint128 floorMarginUSD;\n uint128 nativeCap;\n }\n\n struct DstConfig {\n uint64 lzReceiveBaseGas;\n uint16 multiplierBps;\n uint128 floorMarginUSD; // uses priceFeed PRICE_RATIO_DENOMINATOR\n uint128 nativeCap;\n uint64 lzComposeBaseGas;\n }\n\n struct ExecutionParams {\n address receiver;\n Origin origin;\n bytes32 guid;\n bytes message;\n bytes extraData;\n uint256 gasLimit;\n }\n\n struct NativeDropParams {\n address receiver;\n uint256 amount;\n }\n\n event DstConfigSet(DstConfigParam[] params);\n event NativeDropApplied(Origin origin, uint32 dstEid, address oapp, NativeDropParams[] params, bool[] success);\n\n function dstConfig(uint32 _dstEid) external view returns (uint64, uint16, uint128, uint128, uint64);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IExecutorFeeLib.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { IExecutor } from \"./IExecutor.sol\";\n\ninterface IExecutorFeeLib {\n struct FeeParams {\n address priceFeed;\n uint32 dstEid;\n address sender;\n uint256 calldataSize;\n uint16 defaultMultiplierBps;\n }\n\n struct FeeParamsForRead {\n address priceFeed;\n address sender;\n uint16 defaultMultiplierBps;\n }\n\n error Executor_NoOptions();\n error Executor_NativeAmountExceedsCap(uint256 amount, uint256 cap);\n error Executor_UnsupportedOptionType(uint8 optionType);\n error Executor_InvalidExecutorOptions(uint256 cursor);\n error Executor_ZeroLzReceiveGasProvided();\n error Executor_ZeroLzComposeGasProvided();\n error Executor_ZeroCalldataSizeProvided();\n error Executor_EidNotSupported(uint32 eid);\n\n function getFeeOnSend(\n FeeParams calldata _params,\n IExecutor.DstConfig calldata _dstConfig,\n bytes calldata _options\n ) external returns (uint256 fee);\n\n function getFee(\n FeeParams calldata _params,\n IExecutor.DstConfig calldata _dstConfig,\n bytes calldata _options\n ) external view returns (uint256 fee);\n\n function getFeeOnSend(\n FeeParamsForRead calldata _params,\n IExecutor.DstConfig calldata _dstConfig,\n bytes calldata _options\n ) external returns (uint256 fee);\n\n function getFee(\n FeeParamsForRead calldata _params,\n IExecutor.DstConfig calldata _dstConfig,\n bytes calldata _options\n ) external view returns (uint256 fee);\n\n function version() external view returns (uint64 major, uint8 minor);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/ILayerZeroExecutor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroExecutor {\n // @notice query price and assign jobs at the same time\n // @param _dstEid - the destination endpoint identifier\n // @param _sender - the source sending contract address. executors may apply price discrimination to senders\n // @param _calldataSize - dynamic data size of message + caller params\n // @param _options - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function assignJob(\n uint32 _dstEid,\n address _sender,\n uint256 _calldataSize,\n bytes calldata _options\n ) external returns (uint256 price);\n\n // @notice query the executor price for relaying the payload and its proof to the destination chain\n // @param _dstEid - the destination endpoint identifier\n // @param _sender - the source sending contract address. executors may apply price discrimination to senders\n // @param _calldataSize - dynamic data size of message + caller params\n // @param _options - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function getFee(\n uint32 _dstEid,\n address _sender,\n uint256 _calldataSize,\n bytes calldata _options\n ) external view returns (uint256 price);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/ILayerZeroReadExecutor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroReadExecutor {\n // @notice query price and assign jobs at the same time\n // @param _sender - the source sending contract address. executors may apply price discrimination to senders\n // @param _options - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function assignJob(address _sender, bytes calldata _options) external returns (uint256 fee);\n\n // @notice query the executor price for executing the payload on this chain\n // @param _sender - the source sending contract address. executors may apply price discrimination to senders\n // @param _options - optional parameters for extra service plugins, e.g. sending dust tokens\n function getFee(address _sender, bytes calldata _options) external view returns (uint256 fee);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/ILayerZeroTreasury.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroTreasury {\n function getFee(\n address _sender,\n uint32 _dstEid,\n uint256 _totalNativeFee,\n bool _payInLzToken\n ) external view returns (uint256 fee);\n\n function payFee(\n address _sender,\n uint32 _dstEid,\n uint256 _totalNativeFee,\n bool _payInLzToken\n ) external payable returns (uint256 fee);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IWorker.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IWorker {\n event SetWorkerLib(address workerLib);\n event SetPriceFeed(address priceFeed);\n event SetDefaultMultiplierBps(uint16 multiplierBps);\n event SetSupportedOptionTypes(uint32 dstEid, uint8[] optionTypes);\n event Withdraw(address lib, address to, uint256 amount);\n\n error Worker_NotAllowed();\n error Worker_OnlyMessageLib();\n error Worker_RoleRenouncingDisabled();\n\n function setPriceFeed(address _priceFeed) external;\n\n function priceFeed() external view returns (address);\n\n function setDefaultMultiplierBps(uint16 _multiplierBps) external;\n\n function defaultMultiplierBps() external view returns (uint16);\n\n function withdrawFee(address _lib, address _to, uint256 _amount) external;\n\n function setSupportedOptionTypes(uint32 _eid, uint8[] calldata _optionTypes) external;\n\n function getSupportedOptionTypes(uint32 _eid) external view returns (uint8[] memory);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/libs/ExecutorOptions.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol\";\n\nlibrary ExecutorOptions {\n using CalldataBytesLib for bytes;\n\n uint8 internal constant WORKER_ID = 1;\n\n uint8 internal constant OPTION_TYPE_LZRECEIVE = 1;\n uint8 internal constant OPTION_TYPE_NATIVE_DROP = 2;\n uint8 internal constant OPTION_TYPE_LZCOMPOSE = 3;\n uint8 internal constant OPTION_TYPE_ORDERED_EXECUTION = 4;\n uint8 internal constant OPTION_TYPE_LZREAD = 5;\n\n error Executor_InvalidLzReceiveOption();\n error Executor_InvalidNativeDropOption();\n error Executor_InvalidLzComposeOption();\n error Executor_InvalidLzReadOption();\n\n /// @dev decode the next executor option from the options starting from the specified cursor\n /// @param _options [executor_id][executor_option][executor_id][executor_option]...\n /// executor_option = [option_size][option_type][option]\n /// option_size = len(option_type) + len(option)\n /// executor_id: uint8, option_size: uint16, option_type: uint8, option: bytes\n /// @param _cursor the cursor to start decoding from\n /// @return optionType the type of the option\n /// @return option the option of the executor\n /// @return cursor the cursor to start decoding the next executor option\n function nextExecutorOption(\n bytes calldata _options,\n uint256 _cursor\n ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {\n unchecked {\n // skip worker id\n cursor = _cursor + 1;\n\n // read option size\n uint16 size = _options.toU16(cursor);\n cursor += 2;\n\n // read option type\n optionType = _options.toU8(cursor);\n\n // startCursor and endCursor are used to slice the option from _options\n uint256 startCursor = cursor + 1; // skip option type\n uint256 endCursor = cursor + size;\n option = _options[startCursor:endCursor];\n cursor += size;\n }\n }\n\n function decodeLzReceiveOption(bytes calldata _option) internal pure returns (uint128 gas, uint128 value) {\n if (_option.length != 16 && _option.length != 32) revert Executor_InvalidLzReceiveOption();\n gas = _option.toU128(0);\n value = _option.length == 32 ? _option.toU128(16) : 0;\n }\n\n function decodeNativeDropOption(bytes calldata _option) internal pure returns (uint128 amount, bytes32 receiver) {\n if (_option.length != 48) revert Executor_InvalidNativeDropOption();\n amount = _option.toU128(0);\n receiver = _option.toB32(16);\n }\n\n function decodeLzComposeOption(\n bytes calldata _option\n ) internal pure returns (uint16 index, uint128 gas, uint128 value) {\n if (_option.length != 18 && _option.length != 34) revert Executor_InvalidLzComposeOption();\n index = _option.toU16(0);\n gas = _option.toU128(2);\n value = _option.length == 34 ? _option.toU128(18) : 0;\n }\n\n function decodeLzReadOption(\n bytes calldata _option\n ) internal pure returns (uint128 gas, uint32 calldataSize, uint128 value) {\n if (_option.length != 20 && _option.length != 36) revert Executor_InvalidLzReadOption();\n gas = _option.toU128(0);\n calldataSize = _option.toU32(16);\n value = _option.length == 36 ? _option.toU128(20) : 0;\n }\n\n function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value);\n }\n\n function encodeNativeDropOption(uint128 _amount, bytes32 _receiver) internal pure returns (bytes memory) {\n return abi.encodePacked(_amount, _receiver);\n }\n\n function encodeLzComposeOption(uint16 _index, uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_index, _gas) : abi.encodePacked(_index, _gas, _value);\n }\n\n function encodeLzReadOption(\n uint128 _gas,\n uint32 _calldataSize,\n uint128 _value\n ) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_gas, _calldataSize) : abi.encodePacked(_gas, _calldataSize, _value);\n }\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/libs/SafeCall.sol": { + "content": "// SPDX-License-Identifier: MIT OR Apache-2.0\n\npragma solidity ^0.8.20;\n\n/// @dev copied from https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol.\nlibrary SafeCall {\n /// @notice calls a contract with a specified gas limit and value and captures the return data\n /// @param _target The address to call\n /// @param _gas The amount of gas to forward to the remote contract\n /// @param _value The value in wei to send to the remote contract\n /// to memory.\n /// @param _maxCopy The maximum number of bytes of returndata to copy\n /// to memory.\n /// @param _calldata The data to send to the remote contract\n /// @return success and returndata, as `.call()`. Returndata is capped to\n /// `_maxCopy` bytes.\n function safeCall(\n address _target,\n uint256 _gas,\n uint256 _value,\n uint16 _maxCopy,\n bytes memory _calldata\n ) internal returns (bool, bytes memory) {\n // check that target has code\n uint size;\n assembly {\n size := extcodesize(_target)\n }\n if (size == 0) {\n return (false, new bytes(0));\n }\n\n // set up for assembly call\n uint256 _toCopy;\n bool _success;\n bytes memory _returnData = new bytes(_maxCopy);\n // dispatch message to recipient\n // by assembly calling \"handle\" function\n // we call via assembly to avoid memcopying a very large returndata\n // returned by a malicious contract\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n // limit our copy to 100 bytes\n _toCopy := returndatasize()\n if gt(_toCopy, _maxCopy) {\n _toCopy := _maxCopy\n }\n // Store the length of the copied bytes\n mstore(_returnData, _toCopy)\n // copy the bytes from returndata[0:_toCopy]\n returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n }\n return (_success, _returnData);\n }\n\n /// @notice Use when you _really_ really _really_ don't trust the called\n /// contract. This prevents the called contract from causing reversion of\n /// the caller in as many ways as we can.\n /// @dev The main difference between this and a solidity low-level call is\n /// that we limit the number of bytes that the callee can cause to be\n /// copied to caller memory. This prevents stupid things like malicious\n /// contracts returning 10,000,000 bytes causing a local OOG when copying\n /// to memory.\n /// @param _target The address to call\n /// @param _gas The amount of gas to forward to the remote contract\n /// @param _maxCopy The maximum number of bytes of returndata to copy\n /// to memory.\n /// @param _calldata The data to send to the remote contract\n /// @return success and returndata, as `.call()`. Returndata is capped to\n /// `_maxCopy` bytes.\n function safeStaticCall(\n address _target,\n uint256 _gas,\n uint16 _maxCopy,\n bytes memory _calldata\n ) internal view returns (bool, bytes memory) {\n // check that target has code\n uint size;\n assembly {\n size := extcodesize(_target)\n }\n if (size == 0) {\n return (false, new bytes(0));\n }\n\n // set up for assembly call\n uint256 _toCopy;\n bool _success;\n bytes memory _returnData = new bytes(_maxCopy);\n // dispatch message to recipient\n // by assembly calling \"handle\" function\n // we call via assembly to avoid memcopying a very large returndata\n // returned by a malicious contract\n assembly {\n _success := staticcall(\n _gas, // gas\n _target, // recipient\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n // limit our copy to 256 bytes\n _toCopy := returndatasize()\n if gt(_toCopy, _maxCopy) {\n _toCopy := _maxCopy\n }\n // Store the length of the copied bytes\n mstore(_returnData, _toCopy)\n // copy the bytes from returndata[0:_toCopy]\n returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n }\n return (_success, _returnData);\n }\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/MessageLibBase.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\n/// @dev simply a container of endpoint address and local eid\nabstract contract MessageLibBase {\n address internal immutable endpoint;\n uint32 internal immutable localEid;\n\n error LZ_MessageLib_OnlyEndpoint();\n\n modifier onlyEndpoint() {\n if (endpoint != msg.sender) revert LZ_MessageLib_OnlyEndpoint();\n _;\n }\n\n constructor(address _endpoint, uint32 _localEid) {\n endpoint = _endpoint;\n localEid = _localEid;\n }\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/SendLibBase.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { Transfer } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Transfer.sol\";\n\nimport { ILayerZeroExecutor } from \"./interfaces/ILayerZeroExecutor.sol\";\nimport { ILayerZeroTreasury } from \"./interfaces/ILayerZeroTreasury.sol\";\nimport { SafeCall } from \"./libs/SafeCall.sol\";\nimport { MessageLibBase } from \"./MessageLibBase.sol\";\n\nstruct WorkerOptions {\n uint8 workerId;\n bytes options;\n}\n\nstruct SetDefaultExecutorConfigParam {\n uint32 eid;\n ExecutorConfig config;\n}\n\nstruct ExecutorConfig {\n uint32 maxMessageSize;\n address executor;\n}\n\n/// @dev base contract for both SendLibBaseE1 and SendLibBaseE2\nabstract contract SendLibBase is MessageLibBase, Ownable {\n using SafeCall for address;\n\n address private constant DEFAULT_CONFIG = address(0);\n uint16 internal constant TREASURY_MAX_COPY = 32;\n\n uint256 internal immutable treasuryGasLimit;\n uint256 internal treasuryNativeFeeCap;\n\n // config\n address public treasury;\n mapping(address oapp => mapping(uint32 eid => ExecutorConfig)) public executorConfigs;\n\n // accumulated fees for workers and treasury\n mapping(address worker => uint256) public fees;\n\n event ExecutorFeePaid(address executor, uint256 fee);\n event TreasurySet(address treasury);\n event DefaultExecutorConfigsSet(SetDefaultExecutorConfigParam[] params);\n event ExecutorConfigSet(address oapp, uint32 eid, ExecutorConfig config);\n event TreasuryNativeFeeCapSet(uint256 newTreasuryNativeFeeCap);\n\n error LZ_MessageLib_InvalidMessageSize(uint256 actual, uint256 max);\n error LZ_MessageLib_InvalidAmount(uint256 requested, uint256 available);\n error LZ_MessageLib_TransferFailed();\n error LZ_MessageLib_InvalidExecutor();\n error LZ_MessageLib_ZeroMessageSize();\n\n constructor(\n address _endpoint,\n uint32 _localEid,\n uint256 _treasuryGasLimit,\n uint256 _treasuryNativeFeeCap\n ) MessageLibBase(_endpoint, _localEid) {\n treasuryGasLimit = _treasuryGasLimit;\n treasuryNativeFeeCap = _treasuryNativeFeeCap;\n }\n\n function setDefaultExecutorConfigs(SetDefaultExecutorConfigParam[] calldata _params) external onlyOwner {\n for (uint256 i = 0; i < _params.length; ++i) {\n SetDefaultExecutorConfigParam calldata param = _params[i];\n\n if (param.config.executor == address(0x0)) revert LZ_MessageLib_InvalidExecutor();\n if (param.config.maxMessageSize == 0) revert LZ_MessageLib_ZeroMessageSize();\n\n executorConfigs[DEFAULT_CONFIG][param.eid] = param.config;\n }\n emit DefaultExecutorConfigsSet(_params);\n }\n\n /// @dev the new value can not be greater than the old value, i.e. down only\n function setTreasuryNativeFeeCap(uint256 _newTreasuryNativeFeeCap) external onlyOwner {\n // assert the new value is no greater than the old value\n if (_newTreasuryNativeFeeCap > treasuryNativeFeeCap)\n revert LZ_MessageLib_InvalidAmount(_newTreasuryNativeFeeCap, treasuryNativeFeeCap);\n treasuryNativeFeeCap = _newTreasuryNativeFeeCap;\n emit TreasuryNativeFeeCapSet(_newTreasuryNativeFeeCap);\n }\n\n // ============================ View ===================================\n // @dev get the executor config and if not set, return the default config\n function getExecutorConfig(address _oapp, uint32 _remoteEid) public view returns (ExecutorConfig memory rtnConfig) {\n ExecutorConfig storage defaultConfig = executorConfigs[DEFAULT_CONFIG][_remoteEid];\n ExecutorConfig storage customConfig = executorConfigs[_oapp][_remoteEid];\n\n uint32 maxMessageSize = customConfig.maxMessageSize;\n rtnConfig.maxMessageSize = maxMessageSize != 0 ? maxMessageSize : defaultConfig.maxMessageSize;\n\n address executor = customConfig.executor;\n rtnConfig.executor = executor != address(0x0) ? executor : defaultConfig.executor;\n }\n\n // ======================= Internal =======================\n function _assertMessageSize(uint256 _actual, uint256 _max) internal pure {\n if (_actual > _max) revert LZ_MessageLib_InvalidMessageSize(_actual, _max);\n }\n\n function _payExecutor(\n address _executor,\n uint32 _dstEid,\n address _sender,\n uint256 _msgSize,\n bytes memory _executorOptions\n ) internal returns (uint256 executorFee) {\n executorFee = ILayerZeroExecutor(_executor).assignJob(_dstEid, _sender, _msgSize, _executorOptions);\n if (executorFee > 0) {\n fees[_executor] += executorFee;\n }\n emit ExecutorFeePaid(_executor, executorFee);\n }\n\n function _payTreasury(\n address _sender,\n uint32 _dstEid,\n uint256 _totalNativeFee,\n bool _payInLzToken\n ) internal returns (uint256 treasuryNativeFee, uint256 lzTokenFee) {\n if (treasury != address(0x0)) {\n bytes memory callData = abi.encodeCall(\n ILayerZeroTreasury.payFee,\n (_sender, _dstEid, _totalNativeFee, _payInLzToken)\n );\n (bool success, bytes memory result) = treasury.safeCall(treasuryGasLimit, 0, TREASURY_MAX_COPY, callData);\n\n (treasuryNativeFee, lzTokenFee) = _parseTreasuryResult(_totalNativeFee, _payInLzToken, success, result);\n // fee should be in lzTokenFee if payInLzToken, otherwise in native\n if (treasuryNativeFee > 0) {\n fees[treasury] += treasuryNativeFee;\n }\n }\n }\n\n /// @dev the abstract process for quote() is:\n /// 0/ split out the executor options and options of other workers\n /// 1/ quote workers\n /// 2/ quote executor\n /// 3/ quote treasury\n /// @return nativeFee, lzTokenFee\n function _quote(\n address _sender,\n uint32 _dstEid,\n uint256 _msgSize,\n bool _payInLzToken,\n bytes calldata _options\n ) internal view returns (uint256, uint256) {\n (bytes memory executorOptions, WorkerOptions[] memory validationOptions) = _splitOptions(_options);\n\n // quote the verifier used in the library. for ULN, it is a list of DVNs\n uint256 nativeFee = _quoteVerifier(_sender, _dstEid, validationOptions);\n\n // quote executor\n ExecutorConfig memory config = getExecutorConfig(_sender, _dstEid);\n // assert msg size\n _assertMessageSize(_msgSize, config.maxMessageSize);\n\n nativeFee += ILayerZeroExecutor(config.executor).getFee(_dstEid, _sender, _msgSize, executorOptions);\n\n // quote treasury\n (uint256 treasuryNativeFee, uint256 lzTokenFee) = _quoteTreasury(_sender, _dstEid, nativeFee, _payInLzToken);\n nativeFee += treasuryNativeFee;\n\n return (nativeFee, lzTokenFee);\n }\n\n /// @dev this interface should be DoS-free if the user is paying with native. properties\n /// 1/ treasury can return an overly high lzToken fee\n /// 2/ if treasury returns an overly high native fee, it will be capped by maxNativeFee,\n /// which can be reasoned with the configurations\n /// 3/ the owner can not configure the treasury in a way that force this function to revert\n function _quoteTreasury(\n address _sender,\n uint32 _dstEid,\n uint256 _totalNativeFee,\n bool _payInLzToken\n ) internal view returns (uint256 nativeFee, uint256 lzTokenFee) {\n // treasury must be set, and it has to be a contract\n if (treasury != address(0x0)) {\n bytes memory callData = abi.encodeCall(\n ILayerZeroTreasury.getFee,\n (_sender, _dstEid, _totalNativeFee, _payInLzToken)\n );\n (bool success, bytes memory result) = treasury.safeStaticCall(\n treasuryGasLimit,\n TREASURY_MAX_COPY,\n callData\n );\n\n return _parseTreasuryResult(_totalNativeFee, _payInLzToken, success, result);\n }\n }\n\n function _parseTreasuryResult(\n uint256 _totalNativeFee,\n bool _payInLzToken,\n bool _success,\n bytes memory _result\n ) internal view returns (uint256 nativeFee, uint256 lzTokenFee) {\n // failure, charges nothing\n if (!_success || _result.length < TREASURY_MAX_COPY) return (0, 0);\n\n // parse the result\n uint256 treasureFeeQuote = abi.decode(_result, (uint256));\n if (_payInLzToken) {\n lzTokenFee = treasureFeeQuote;\n } else {\n // pay in native\n // we must prevent high-treasuryFee Dos attack\n // nativeFee = min(treasureFeeQuote, maxNativeFee)\n // opportunistically raise the maxNativeFee to be the same as _totalNativeFee\n // can't use the _totalNativeFee alone because the oapp can use custom workers to force the fee to 0.\n // maxNativeFee = max (_totalNativeFee, treasuryNativeFeeCap)\n uint256 maxNativeFee = _totalNativeFee > treasuryNativeFeeCap ? _totalNativeFee : treasuryNativeFeeCap;\n\n // min (treasureFeeQuote, nativeFeeCap)\n nativeFee = treasureFeeQuote > maxNativeFee ? maxNativeFee : treasureFeeQuote;\n }\n }\n\n /// @dev authenticated by msg.sender only\n function _debitFee(uint256 _amount) internal {\n uint256 fee = fees[msg.sender];\n if (_amount > fee) revert LZ_MessageLib_InvalidAmount(_amount, fee);\n unchecked {\n fees[msg.sender] = fee - _amount;\n }\n }\n\n function _setTreasury(address _treasury) internal {\n treasury = _treasury;\n emit TreasurySet(_treasury);\n }\n\n function _setExecutorConfig(uint32 _remoteEid, address _oapp, ExecutorConfig memory _config) internal {\n executorConfigs[_oapp][_remoteEid] = _config;\n emit ExecutorConfigSet(_oapp, _remoteEid, _config);\n }\n\n // ======================= Virtual =======================\n /// @dev these two functions will be overridden with specific logics of the library function\n function _quoteVerifier(\n address _oapp,\n uint32 _eid,\n WorkerOptions[] memory _options\n ) internal view virtual returns (uint256 nativeFee);\n\n /// @dev this function will split the options into executorOptions and validationOptions\n function _splitOptions(\n bytes calldata _options\n ) internal view virtual returns (bytes memory executorOptions, WorkerOptions[] memory validationOptions);\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/DVNOptions.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { BytesLib } from \"solidity-bytes-utils/contracts/BytesLib.sol\";\n\nimport { BitMap256 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol\";\nimport { CalldataBytesLib } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol\";\n\nlibrary DVNOptions {\n using CalldataBytesLib for bytes;\n using BytesLib for bytes;\n\n uint8 internal constant WORKER_ID = 2;\n uint8 internal constant OPTION_TYPE_PRECRIME = 1;\n\n error DVN_InvalidDVNIdx();\n error DVN_InvalidDVNOptions(uint256 cursor);\n\n /// @dev group dvn options by its idx\n /// @param _options [dvn_id][dvn_option][dvn_id][dvn_option]...\n /// dvn_option = [option_size][dvn_idx][option_type][option]\n /// option_size = len(dvn_idx) + len(option_type) + len(option)\n /// dvn_id: uint8, dvn_idx: uint8, option_size: uint16, option_type: uint8, option: bytes\n /// @return dvnOptions the grouped options, still share the same format of _options\n /// @return dvnIndices the dvn indices\n function groupDVNOptionsByIdx(\n bytes memory _options\n ) internal pure returns (bytes[] memory dvnOptions, uint8[] memory dvnIndices) {\n if (_options.length == 0) return (dvnOptions, dvnIndices);\n\n uint8 numDVNs = getNumDVNs(_options);\n\n // if there is only 1 dvn, we can just return the whole options\n if (numDVNs == 1) {\n dvnOptions = new bytes[](1);\n dvnOptions[0] = _options;\n\n dvnIndices = new uint8[](1);\n dvnIndices[0] = _options.toUint8(3); // dvn idx\n return (dvnOptions, dvnIndices);\n }\n\n // otherwise, we need to group the options by dvn_idx\n dvnIndices = new uint8[](numDVNs);\n dvnOptions = new bytes[](numDVNs);\n unchecked {\n uint256 cursor = 0;\n uint256 start = 0;\n uint8 lastDVNIdx = 255; // 255 is an invalid dvn_idx\n\n while (cursor < _options.length) {\n ++cursor; // skip worker_id\n\n // optionLength asserted in getNumDVNs (skip check)\n uint16 optionLength = _options.toUint16(cursor);\n cursor += 2;\n\n // dvnIdx asserted in getNumDVNs (skip check)\n uint8 dvnIdx = _options.toUint8(cursor);\n\n // dvnIdx must equal to the lastDVNIdx for the first option\n // so it is always skipped in the first option\n // this operation slices out options whenever the scan finds a different lastDVNIdx\n if (lastDVNIdx == 255) {\n lastDVNIdx = dvnIdx;\n } else if (dvnIdx != lastDVNIdx) {\n uint256 len = cursor - start - 3; // 3 is for worker_id and option_length\n bytes memory opt = _options.slice(start, len);\n _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, opt);\n\n // reset the start and lastDVNIdx\n start += len;\n lastDVNIdx = dvnIdx;\n }\n\n cursor += optionLength;\n }\n\n // skip check the cursor here because the cursor is asserted in getNumDVNs\n // if we have reached the end of the options, we need to process the last dvn\n uint256 size = cursor - start;\n bytes memory op = _options.slice(start, size);\n _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, op);\n\n // revert dvnIndices to start from 0\n for (uint8 i = 0; i < numDVNs; ++i) {\n --dvnIndices[i];\n }\n }\n }\n\n function _insertDVNOptions(\n bytes[] memory _dvnOptions,\n uint8[] memory _dvnIndices,\n uint8 _dvnIdx,\n bytes memory _newOptions\n ) internal pure {\n // dvnIdx starts from 0 but default value of dvnIndices is 0,\n // so we tell if the slot is empty by adding 1 to dvnIdx\n if (_dvnIdx == 255) revert DVN_InvalidDVNIdx();\n uint8 dvnIdxAdj = _dvnIdx + 1;\n\n for (uint256 j = 0; j < _dvnIndices.length; ++j) {\n uint8 index = _dvnIndices[j];\n if (dvnIdxAdj == index) {\n _dvnOptions[j] = abi.encodePacked(_dvnOptions[j], _newOptions);\n break;\n } else if (index == 0) {\n // empty slot, that means it is the first time we see this dvn\n _dvnIndices[j] = dvnIdxAdj;\n _dvnOptions[j] = _newOptions;\n break;\n }\n }\n }\n\n /// @dev get the number of unique dvns\n /// @param _options the format is the same as groupDVNOptionsByIdx\n function getNumDVNs(bytes memory _options) internal pure returns (uint8 numDVNs) {\n uint256 cursor = 0;\n BitMap256 bitmap;\n\n // find number of unique dvn_idx\n unchecked {\n while (cursor < _options.length) {\n ++cursor; // skip worker_id\n\n uint16 optionLength = _options.toUint16(cursor);\n cursor += 2;\n if (optionLength < 2) revert DVN_InvalidDVNOptions(cursor); // at least 1 byte for dvn_idx and 1 byte for option_type\n\n uint8 dvnIdx = _options.toUint8(cursor);\n\n // if dvnIdx is not set, increment numDVNs\n // max num of dvns is 255, 255 is an invalid dvn_idx\n // The order of the dvnIdx is not required to be sequential, as enforcing the order may weaken\n // the composability of the options. e.g. if we refrain from enforcing the order, an OApp that has\n // already enforced certain options can append additional options to the end of the enforced\n // ones without restrictions.\n if (dvnIdx == 255) revert DVN_InvalidDVNIdx();\n if (!bitmap.get(dvnIdx)) {\n ++numDVNs;\n bitmap = bitmap.set(dvnIdx);\n }\n\n cursor += optionLength;\n }\n }\n if (cursor != _options.length) revert DVN_InvalidDVNOptions(cursor);\n }\n\n /// @dev decode the next dvn option from _options starting from the specified cursor\n /// @param _options the format is the same as groupDVNOptionsByIdx\n /// @param _cursor the cursor to start decoding\n /// @return optionType the type of the option\n /// @return option the option\n /// @return cursor the cursor to start decoding the next option\n function nextDVNOption(\n bytes calldata _options,\n uint256 _cursor\n ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {\n unchecked {\n // skip worker id\n cursor = _cursor + 1;\n\n // read option size\n uint16 size = _options.toU16(cursor);\n cursor += 2;\n\n // read option type\n optionType = _options.toU8(cursor + 1); // skip dvn_idx\n\n // startCursor and endCursor are used to slice the option from _options\n uint256 startCursor = cursor + 2; // skip option type and dvn_idx\n uint256 endCursor = cursor + size;\n option = _options[startCursor:endCursor];\n cursor += size;\n }\n }\n}\n" + }, + "@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/UlnOptions.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport { ExecutorOptions } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/ExecutorOptions.sol\";\n\nimport { DVNOptions } from \"./DVNOptions.sol\";\n\nlibrary UlnOptions {\n using SafeCast for uint256;\n\n uint16 internal constant TYPE_1 = 1; // legacy options type 1\n uint16 internal constant TYPE_2 = 2; // legacy options type 2\n uint16 internal constant TYPE_3 = 3;\n\n error LZ_ULN_InvalidWorkerOptions(uint256 cursor);\n error LZ_ULN_InvalidWorkerId(uint8 workerId);\n error LZ_ULN_InvalidLegacyType1Option();\n error LZ_ULN_InvalidLegacyType2Option();\n error LZ_ULN_UnsupportedOptionType(uint16 optionType);\n\n /// @dev decode the options into executorOptions and dvnOptions\n /// @param _options the options can be either legacy options (type 1 or 2) or type 3 options\n /// @return executorOptions the executor options, share the same format of type 3 options\n /// @return dvnOptions the dvn options, share the same format of type 3 options\n function decode(\n bytes calldata _options\n ) internal pure returns (bytes memory executorOptions, bytes memory dvnOptions) {\n // at least 2 bytes for the option type, but can have no options\n if (_options.length < 2) revert LZ_ULN_InvalidWorkerOptions(0);\n\n uint16 optionsType = uint16(bytes2(_options[0:2]));\n uint256 cursor = 2;\n\n // type3 options: [worker_option][worker_option]...\n // worker_option: [worker_id][option_size][option]\n // worker_id: uint8, option_size: uint16, option: bytes\n if (optionsType == TYPE_3) {\n unchecked {\n uint256 start = cursor;\n uint8 lastWorkerId; // worker_id starts from 1, so 0 is an invalid worker_id\n\n // heuristic: we assume that the options are mostly EXECUTOR options only\n // checking the workerID can reduce gas usage for most cases\n while (cursor < _options.length) {\n uint8 workerId = uint8(bytes1(_options[cursor:cursor + 1]));\n if (workerId == 0) revert LZ_ULN_InvalidWorkerId(0);\n\n // workerId must equal to the lastWorkerId for the first option\n // so it is always skipped in the first option\n // this operation slices out options whenever the the scan finds a different workerId\n if (lastWorkerId == 0) {\n lastWorkerId = workerId;\n } else if (workerId != lastWorkerId) {\n bytes calldata op = _options[start:cursor]; // slice out the last worker's options\n (executorOptions, dvnOptions) = _insertWorkerOptions(\n executorOptions,\n dvnOptions,\n lastWorkerId,\n op\n );\n\n // reset the start cursor and lastWorkerId\n start = cursor;\n lastWorkerId = workerId;\n }\n\n ++cursor; // for workerId\n\n uint16 size = uint16(bytes2(_options[cursor:cursor + 2]));\n if (size == 0) revert LZ_ULN_InvalidWorkerOptions(cursor);\n cursor += size + 2;\n }\n\n // the options length must be the same as the cursor at the end\n if (cursor != _options.length) revert LZ_ULN_InvalidWorkerOptions(cursor);\n\n // if we have reached the end of the options and the options are not empty\n // we need to process the last worker's options\n if (_options.length > 2) {\n bytes calldata op = _options[start:cursor];\n (executorOptions, dvnOptions) = _insertWorkerOptions(executorOptions, dvnOptions, lastWorkerId, op);\n }\n }\n } else {\n executorOptions = decodeLegacyOptions(optionsType, _options);\n }\n }\n\n function _insertWorkerOptions(\n bytes memory _executorOptions,\n bytes memory _dvnOptions,\n uint8 _workerId,\n bytes calldata _newOptions\n ) private pure returns (bytes memory, bytes memory) {\n if (_workerId == ExecutorOptions.WORKER_ID) {\n _executorOptions = _executorOptions.length == 0\n ? _newOptions\n : abi.encodePacked(_executorOptions, _newOptions);\n } else if (_workerId == DVNOptions.WORKER_ID) {\n _dvnOptions = _dvnOptions.length == 0 ? _newOptions : abi.encodePacked(_dvnOptions, _newOptions);\n } else {\n revert LZ_ULN_InvalidWorkerId(_workerId);\n }\n return (_executorOptions, _dvnOptions);\n }\n\n /// @dev decode the legacy options (type 1 or 2) into executorOptions\n /// @param _optionType the legacy option type\n /// @param _options the legacy options, which still has the option type in the first 2 bytes\n /// @return executorOptions the executor options, share the same format of type 3 options\n /// Data format:\n /// legacy type 1: [extraGas]\n /// legacy type 2: [extraGas][dstNativeAmt][dstNativeAddress]\n /// extraGas: uint256, dstNativeAmt: uint256, dstNativeAddress: bytes\n function decodeLegacyOptions(\n uint16 _optionType,\n bytes calldata _options\n ) internal pure returns (bytes memory executorOptions) {\n if (_optionType == TYPE_1) {\n if (_options.length != 34) revert LZ_ULN_InvalidLegacyType1Option();\n\n // execution gas\n uint128 executionGas = uint256(bytes32(_options[2:2 + 32])).toUint128();\n\n // dont use the encode function in the ExecutorOptions lib for saving gas by calling abi.encodePacked once\n // the result is a lzReceive option: [executor_id][option_size][option_type][execution_gas]\n // option_type: uint8, execution_gas: uint128\n // option_size = len(option_type) + len(execution_gas) = 1 + 16 = 17\n executorOptions = abi.encodePacked(\n ExecutorOptions.WORKER_ID,\n uint16(17), // 16 + 1, 16 for option_length, + 1 for option_type\n ExecutorOptions.OPTION_TYPE_LZRECEIVE,\n executionGas\n );\n } else if (_optionType == TYPE_2) {\n // receiver size <= 32\n if (_options.length <= 66 || _options.length > 98) revert LZ_ULN_InvalidLegacyType2Option();\n\n // execution gas\n uint128 executionGas = uint256(bytes32(_options[2:2 + 32])).toUint128();\n\n // nativeDrop (amount + receiver)\n uint128 amount = uint256(bytes32(_options[34:34 + 32])).toUint128(); // offset 2 + 32\n bytes32 receiver;\n unchecked {\n uint256 receiverLen = _options.length - 66; // offset 2 + 32 + 32\n receiver = bytes32(_options[66:]);\n receiver = receiver >> (8 * (32 - receiverLen)); // padding 0 to the left\n }\n\n // dont use the encode function in the ExecutorOptions lib for saving gas by calling abi.encodePacked once\n // the result has one lzReceive option and one nativeDrop option:\n // [executor_id][lzReceive_option_size][option_type][execution_gas] +\n // [executor_id][nativeDrop_option_size][option_type][nativeDrop_amount][receiver]\n // option_type: uint8, execution_gas: uint128, nativeDrop_amount: uint128, receiver: bytes32\n // lzReceive_option_size = len(option_type) + len(execution_gas) = 1 + 16 = 17\n // nativeDrop_option_size = len(option_type) + len(nativeDrop_amount) + len(receiver) = 1 + 16 + 32 = 49\n executorOptions = abi.encodePacked(\n ExecutorOptions.WORKER_ID,\n uint16(17), // 16 + 1, 16 for option_length, + 1 for option_type\n ExecutorOptions.OPTION_TYPE_LZRECEIVE,\n executionGas,\n ExecutorOptions.WORKER_ID,\n uint16(49), // 48 + 1, 32 + 16 for option_length, + 1 for option_type\n ExecutorOptions.OPTION_TYPE_NATIVE_DROP,\n amount,\n receiver\n );\n } else {\n revert LZ_ULN_UnsupportedOptionType(_optionType);\n }\n }\n}\n" + }, + "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/IOAppCore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ILayerZeroEndpointV2 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\n\n/**\n * @title IOAppCore\n */\ninterface IOAppCore {\n // Custom error messages\n error OnlyPeer(uint32 eid, bytes32 sender);\n error NoPeer(uint32 eid);\n error InvalidEndpointCall();\n error InvalidDelegate();\n\n // Event emitted when a peer (OApp) is set for a corresponding endpoint\n event PeerSet(uint32 eid, bytes32 peer);\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n */\n function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);\n\n /**\n * @notice Retrieves the LayerZero endpoint associated with the OApp.\n * @return iEndpoint The LayerZero endpoint as an interface.\n */\n function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);\n\n /**\n * @notice Retrieves the peer (OApp) associated with a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @return peer The peer address (OApp instance) associated with the corresponding endpoint.\n */\n function peers(uint32 _eid) external view returns (bytes32 peer);\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n */\n function setPeer(uint32 _eid, bytes32 _peer) external;\n\n /**\n * @notice Sets the delegate address for the OApp Core.\n * @param _delegate The address of the delegate to be set.\n */\n function setDelegate(address _delegate) external;\n}\n" + }, + "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OAppCore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IOAppCore, ILayerZeroEndpointV2 } from \"./interfaces/IOAppCore.sol\";\n\n/**\n * @title OAppCore\n * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.\n */\nabstract contract OAppCore is IOAppCore, Ownable {\n // The LayerZero endpoint associated with the given OApp\n ILayerZeroEndpointV2 public immutable endpoint;\n\n // Mapping to store peers associated with corresponding endpoints\n mapping(uint32 eid => bytes32 peer) public peers;\n\n /**\n * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.\n * @param _endpoint The address of the LOCAL Layer Zero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n *\n * @dev The delegate typically should be set as the owner of the contract.\n */\n constructor(address _endpoint, address _delegate) {\n endpoint = ILayerZeroEndpointV2(_endpoint);\n\n if (_delegate == address(0)) revert InvalidDelegate();\n endpoint.setDelegate(_delegate);\n }\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.\n * @dev Set this to bytes32(0) to remove the peer address.\n * @dev Peer is a bytes32 to accommodate non-evm chains.\n */\n function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {\n _setPeer(_eid, _peer);\n }\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n *\n * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.\n * @dev Set this to bytes32(0) to remove the peer address.\n * @dev Peer is a bytes32 to accommodate non-evm chains.\n */\n function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {\n peers[_eid] = _peer;\n emit PeerSet(_eid, _peer);\n }\n\n /**\n * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.\n * ie. the peer is set to bytes32(0).\n * @param _eid The endpoint ID.\n * @return peer The address of the peer associated with the specified endpoint.\n */\n function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {\n bytes32 peer = peers[_eid];\n if (peer == bytes32(0)) revert NoPeer(_eid);\n return peer;\n }\n\n /**\n * @notice Sets the delegate address for the OApp.\n * @param _delegate The address of the delegate to be set.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.\n */\n function setDelegate(address _delegate) public onlyOwner {\n endpoint.setDelegate(_delegate);\n }\n}\n" + }, + "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OAppSender.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { SafeERC20, IERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { MessagingParams, MessagingFee, MessagingReceipt } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OAppSender\n * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.\n */\nabstract contract OAppSender is OAppCore {\n using SafeERC20 for IERC20;\n\n // Custom error messages\n error NotEnoughNative(uint256 msgValue);\n error LzTokenUnavailable();\n\n // @dev The version of the OAppSender implementation.\n // @dev Version is bumped when changes are made to this contract.\n uint64 internal constant SENDER_VERSION = 1;\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n *\n * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.\n * ie. this is a SEND only OApp.\n * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions\n */\n function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {\n return (SENDER_VERSION, 0);\n }\n\n /**\n * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.\n * @param _dstEid The destination endpoint ID.\n * @param _message The message payload.\n * @param _options Additional options for the message.\n * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.\n * @return fee The calculated MessagingFee for the message.\n * - nativeFee: The native fee for the message.\n * - lzTokenFee: The LZ token fee for the message.\n */\n function _quote(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n bool _payInLzToken\n ) internal view virtual returns (MessagingFee memory fee) {\n return\n endpoint.quote(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),\n address(this)\n );\n }\n\n /**\n * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.\n * @param _dstEid The destination endpoint ID.\n * @param _message The message payload.\n * @param _options Additional options for the message.\n * @param _fee The calculated LayerZero fee for the message.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess fee values sent to the endpoint.\n * @return receipt The receipt for the sent message.\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function _lzSend(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n MessagingFee memory _fee,\n address _refundAddress\n ) internal virtual returns (MessagingReceipt memory receipt) {\n // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.\n uint256 messageValue = _payNative(_fee.nativeFee);\n if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);\n\n return\n // solhint-disable-next-line check-send-result\n endpoint.send{ value: messageValue }(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),\n _refundAddress\n );\n }\n\n /**\n * @dev Internal function to pay the native fee associated with the message.\n * @param _nativeFee The native fee to be paid.\n * @return nativeFee The amount of native currency paid.\n *\n * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,\n * this will need to be overridden because msg.value would contain multiple lzFees.\n * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.\n * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.\n * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.\n */\n function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {\n if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);\n return _nativeFee;\n }\n\n /**\n * @dev Internal function to pay the LZ token fee associated with the message.\n * @param _lzTokenFee The LZ token fee to be paid.\n *\n * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.\n * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().\n */\n function _payLzToken(uint256 _lzTokenFee) internal virtual {\n // @dev Cannot cache the token because it is not immutable in the endpoint.\n address lzToken = endpoint.lzToken();\n if (lzToken == address(0)) revert LzTokenUnavailable();\n\n // Pay LZ token fee by sending tokens to the endpoint.\n IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);\n }\n}\n" + }, + "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { MessagingReceipt, MessagingFee } from \"../../oapp/OAppSender.sol\";\n\n/**\n * @dev Struct representing token parameters for the OFT send() operation.\n */\nstruct SendParam {\n uint32 dstEid; // Destination endpoint ID.\n bytes32 to; // Recipient address.\n uint256 amountLD; // Amount to send in local decimals.\n uint256 minAmountLD; // Minimum amount to send in local decimals.\n bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.\n bytes composeMsg; // The composed message for the send() operation.\n bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.\n}\n\n/**\n * @dev Struct representing OFT limit information.\n * @dev These amounts can change dynamically and are up the the specific oft implementation.\n */\nstruct OFTLimit {\n uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.\n uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.\n}\n\n/**\n * @dev Struct representing OFT receipt information.\n */\nstruct OFTReceipt {\n uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.\n // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.\n uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.\n}\n\n/**\n * @dev Struct representing OFT fee details.\n * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.\n */\nstruct OFTFeeDetail {\n int256 feeAmountLD; // Amount of the fee in local decimals.\n string description; // Description of the fee.\n}\n\n/**\n * @title IOFT\n * @dev Interface for the OftChain (OFT) token.\n * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.\n * @dev This specific interface ID is '0x02e49c2c'.\n */\ninterface IOFT {\n // Custom error messages\n error InvalidLocalDecimals();\n error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);\n\n // Events\n event OFTSent(\n bytes32 indexed guid, // GUID of the OFT message.\n uint32 dstEid, // Destination Endpoint ID.\n address indexed fromAddress, // Address of the sender on the src chain.\n uint256 amountSentLD, // Amount of tokens sent in local decimals.\n uint256 amountReceivedLD // Amount of tokens received in local decimals.\n );\n event OFTReceived(\n bytes32 indexed guid, // GUID of the OFT message.\n uint32 srcEid, // Source Endpoint ID.\n address indexed toAddress, // Address of the recipient on the dst chain.\n uint256 amountReceivedLD // Amount of tokens received in local decimals.\n );\n\n /**\n * @notice Retrieves interfaceID and the version of the OFT.\n * @return interfaceId The interface ID.\n * @return version The version.\n *\n * @dev interfaceId: This specific interface ID is '0x02e49c2c'.\n * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.\n * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.\n * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\n */\n function oftVersion() external view returns (bytes4 interfaceId, uint64 version);\n\n /**\n * @notice Retrieves the address of the token associated with the OFT.\n * @return token The address of the ERC20 token implementation.\n */\n function token() external view returns (address);\n\n /**\n * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.\n * @return requiresApproval Needs approval of the underlying token implementation.\n *\n * @dev Allows things like wallet implementers to determine integration requirements,\n * without understanding the underlying token implementation.\n */\n function approvalRequired() external view returns (bool);\n\n /**\n * @notice Retrieves the shared decimals of the OFT.\n * @return sharedDecimals The shared decimals of the OFT.\n */\n function sharedDecimals() external view returns (uint8);\n\n /**\n * @notice Provides a quote for OFT-related operations.\n * @param _sendParam The parameters for the send operation.\n * @return limit The OFT limit information.\n * @return oftFeeDetails The details of OFT fees.\n * @return receipt The OFT receipt information.\n */\n function quoteOFT(\n SendParam calldata _sendParam\n ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);\n\n /**\n * @notice Provides a quote for the send() operation.\n * @param _sendParam The parameters for the send() operation.\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\n * @return fee The calculated LayerZero messaging fee from the send() operation.\n *\n * @dev MessagingFee: LayerZero msg fee\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n */\n function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);\n\n /**\n * @notice Executes the send() operation.\n * @param _sendParam The parameters for the send operation.\n * @param _fee The fee information supplied by the caller.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess funds from fees etc. on the src.\n * @return receipt The LayerZero messaging receipt from the send() operation.\n * @return oftReceipt The OFT receipt information.\n *\n * @dev MessagingReceipt: LayerZero msg receipt\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function send(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) external payable returns (MessagingReceipt memory, OFTReceipt memory);\n}\n" + }, + "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nlibrary OFTComposeMsgCodec {\n // Offset constants for decoding composed messages\n uint8 private constant NONCE_OFFSET = 8;\n uint8 private constant SRC_EID_OFFSET = 12;\n uint8 private constant AMOUNT_LD_OFFSET = 44;\n uint8 private constant COMPOSE_FROM_OFFSET = 76;\n\n /**\n * @dev Encodes a OFT composed message.\n * @param _nonce The nonce value.\n * @param _srcEid The source endpoint ID.\n * @param _amountLD The amount in local decimals.\n * @param _composeMsg The composed message.\n * @return _msg The encoded Composed message.\n */\n function encode(\n uint64 _nonce,\n uint32 _srcEid,\n uint256 _amountLD,\n bytes memory _composeMsg // 0x[composeFrom][composeMsg]\n ) internal pure returns (bytes memory _msg) {\n _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);\n }\n\n /**\n * @dev Retrieves the nonce from the composed message.\n * @param _msg The message.\n * @return The nonce value.\n */\n function nonce(bytes calldata _msg) internal pure returns (uint64) {\n return uint64(bytes8(_msg[:NONCE_OFFSET]));\n }\n\n /**\n * @dev Retrieves the source endpoint ID from the composed message.\n * @param _msg The message.\n * @return The source endpoint ID.\n */\n function srcEid(bytes calldata _msg) internal pure returns (uint32) {\n return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));\n }\n\n /**\n * @dev Retrieves the amount in local decimals from the composed message.\n * @param _msg The message.\n * @return The amount in local decimals.\n */\n function amountLD(bytes calldata _msg) internal pure returns (uint256) {\n return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));\n }\n\n /**\n * @dev Retrieves the composeFrom value from the composed message.\n * @param _msg The message.\n * @return The composeFrom value.\n */\n function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {\n return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);\n }\n\n /**\n * @dev Retrieves the composed message.\n * @param _msg The message.\n * @return The composed message.\n */\n function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {\n return _msg[COMPOSE_FROM_OFFSET:];\n }\n\n /**\n * @dev Converts an address to bytes32.\n * @param _addr The address to convert.\n * @return The bytes32 representation of the address.\n */\n function addressToBytes32(address _addr) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(_addr)));\n }\n\n /**\n * @dev Converts bytes32 to an address.\n * @param _b The bytes32 value to convert.\n * @return The address representation of bytes32.\n */\n function bytes32ToAddress(bytes32 _b) internal pure returns (address) {\n return address(uint160(uint256(_b)));\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/EndpointV2ViewUpgradeable.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"./interfaces/ILayerZeroEndpointV2.sol\";\n\nenum ExecutionState {\n NotExecutable, // executor: waits for PayloadVerified event and starts polling for executable\n VerifiedButNotExecutable, // executor: starts active polling for executable\n Executable,\n Executed\n}\n\ncontract EndpointV2ViewUpgradeable is Initializable {\n bytes32 public constant EMPTY_PAYLOAD_HASH = bytes32(0);\n bytes32 public constant NIL_PAYLOAD_HASH = bytes32(type(uint256).max);\n\n ILayerZeroEndpointV2 public endpoint;\n\n function __EndpointV2View_init(address _endpoint) internal onlyInitializing {\n __EndpointV2View_init_unchained(_endpoint);\n }\n\n function __EndpointV2View_init_unchained(address _endpoint) internal onlyInitializing {\n endpoint = ILayerZeroEndpointV2(_endpoint);\n }\n\n function initializable(Origin memory _origin, address _receiver) public view returns (bool) {\n try endpoint.initializable(_origin, _receiver) returns (bool _initializable) {\n return _initializable;\n } catch {\n return false;\n }\n }\n\n /// @dev check if a message is verifiable.\n function verifiable(\n Origin memory _origin,\n address _receiver,\n address _receiveLib,\n bytes32 _payloadHash\n ) public view returns (bool) {\n if (!endpoint.isValidReceiveLibrary(_receiver, _origin.srcEid, _receiveLib)) return false;\n\n if (!endpoint.verifiable(_origin, _receiver)) return false;\n\n // checked in _inbound for verify\n if (_payloadHash == EMPTY_PAYLOAD_HASH) return false;\n\n return true;\n }\n\n /// @dev check if a message is executable.\n /// @return ExecutionState of Executed, Executable, or NotExecutable\n function executable(Origin memory _origin, address _receiver) public view returns (ExecutionState) {\n bytes32 payloadHash = endpoint.inboundPayloadHash(_receiver, _origin.srcEid, _origin.sender, _origin.nonce);\n\n // executed if the payload hash has been cleared and the nonce is less than or equal to lazyInboundNonce\n if (\n payloadHash == EMPTY_PAYLOAD_HASH &&\n _origin.nonce <= endpoint.lazyInboundNonce(_receiver, _origin.srcEid, _origin.sender)\n ) {\n return ExecutionState.Executed;\n }\n\n // executable if nonce has not been executed and has not been nilified and nonce is less than or equal to inboundNonce\n if (\n payloadHash != NIL_PAYLOAD_HASH &&\n _origin.nonce <= endpoint.inboundNonce(_receiver, _origin.srcEid, _origin.sender)\n ) {\n return ExecutionState.Executable;\n }\n\n // only start active executable polling if payload hash is not empty nor nil\n if (payloadHash != EMPTY_PAYLOAD_HASH && payloadHash != NIL_PAYLOAD_HASH) {\n return ExecutionState.VerifiedButNotExecutable;\n }\n\n // return NotExecutable as a catch-all\n return ExecutionState.NotExecutable;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\n/**\n * @title ILayerZeroComposer\n */\ninterface ILayerZeroComposer {\n /**\n * @notice Composes a LayerZero message from an OApp.\n * @dev To ensure non-reentrancy, implementers of this interface MUST assert msg.sender is the corresponding EndpointV2 contract (i.e., onlyEndpointV2).\n * @param _from The address initiating the composition, typically the OApp where the lzReceive was called.\n * @param _guid The unique identifier for the corresponding LayerZero src/dst tx.\n * @param _message The composed message payload in bytes. NOT necessarily the same payload passed via lzReceive.\n * @param _executor The address of the executor for the composed message.\n * @param _extraData Additional arbitrary data in bytes passed by the entity who executes the lzCompose.\n */\n function lzCompose(\n address _from,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable;\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { IMessageLibManager } from \"./IMessageLibManager.sol\";\nimport { IMessagingComposer } from \"./IMessagingComposer.sol\";\nimport { IMessagingChannel } from \"./IMessagingChannel.sol\";\nimport { IMessagingContext } from \"./IMessagingContext.sol\";\n\nstruct MessagingParams {\n uint32 dstEid;\n bytes32 receiver;\n bytes message;\n bytes options;\n bool payInLzToken;\n}\n\nstruct MessagingReceipt {\n bytes32 guid;\n uint64 nonce;\n MessagingFee fee;\n}\n\nstruct MessagingFee {\n uint256 nativeFee;\n uint256 lzTokenFee;\n}\n\nstruct Origin {\n uint32 srcEid;\n bytes32 sender;\n uint64 nonce;\n}\n\ninterface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {\n event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);\n\n event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);\n\n event PacketDelivered(Origin origin, address receiver);\n\n event LzReceiveAlert(\n address indexed receiver,\n address indexed executor,\n Origin origin,\n bytes32 guid,\n uint256 gas,\n uint256 value,\n bytes message,\n bytes extraData,\n bytes reason\n );\n\n event LzTokenSet(address token);\n\n event DelegateSet(address sender, address delegate);\n\n function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);\n\n function send(\n MessagingParams calldata _params,\n address _refundAddress\n ) external payable returns (MessagingReceipt memory);\n\n function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;\n\n function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);\n\n function initializable(Origin calldata _origin, address _receiver) external view returns (bool);\n\n function lzReceive(\n Origin calldata _origin,\n address _receiver,\n bytes32 _guid,\n bytes calldata _message,\n bytes calldata _extraData\n ) external payable;\n\n // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order\n function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;\n\n function setLzToken(address _lzToken) external;\n\n function lzToken() external view returns (address);\n\n function nativeToken() external view returns (address);\n\n function setDelegate(address _delegate) external;\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { Origin } from \"./ILayerZeroEndpointV2.sol\";\n\ninterface ILayerZeroReceiver {\n function allowInitializePath(Origin calldata _origin) external view returns (bool);\n\n function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);\n\n function lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable;\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\nimport { SetConfigParam } from \"./IMessageLibManager.sol\";\n\nenum MessageLibType {\n Send,\n Receive,\n SendAndReceive\n}\n\ninterface IMessageLib is IERC165 {\n function setConfig(address _oapp, SetConfigParam[] calldata _config) external;\n\n function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);\n\n function isSupportedEid(uint32 _eid) external view returns (bool);\n\n // message libs of same major version are compatible\n function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);\n\n function messageLibType() external view returns (MessageLibType);\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nstruct SetConfigParam {\n uint32 eid;\n uint32 configType;\n bytes config;\n}\n\ninterface IMessageLibManager {\n struct Timeout {\n address lib;\n uint256 expiry;\n }\n\n event LibraryRegistered(address newLib);\n event DefaultSendLibrarySet(uint32 eid, address newLib);\n event DefaultReceiveLibrarySet(uint32 eid, address newLib);\n event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);\n event SendLibrarySet(address sender, uint32 eid, address newLib);\n event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);\n event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);\n\n function registerLibrary(address _lib) external;\n\n function isRegisteredLibrary(address _lib) external view returns (bool);\n\n function getRegisteredLibraries() external view returns (address[] memory);\n\n function setDefaultSendLibrary(uint32 _eid, address _newLib) external;\n\n function defaultSendLibrary(uint32 _eid) external view returns (address);\n\n function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;\n\n function defaultReceiveLibrary(uint32 _eid) external view returns (address);\n\n function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;\n\n function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);\n\n function isSupportedEid(uint32 _eid) external view returns (bool);\n\n function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);\n\n /// ------------------- OApp interfaces -------------------\n function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;\n\n function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);\n\n function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);\n\n function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;\n\n function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);\n\n function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;\n\n function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);\n\n function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;\n\n function getConfig(\n address _oapp,\n address _lib,\n uint32 _eid,\n uint32 _configType\n ) external view returns (bytes memory config);\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IMessagingChannel {\n event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);\n event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);\n event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);\n\n function eid() external view returns (uint32);\n\n // this is an emergency function if a message cannot be verified for some reasons\n // required to provide _nextNonce to avoid race condition\n function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;\n\n function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;\n\n function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;\n\n function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);\n\n function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);\n\n function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);\n\n function inboundPayloadHash(\n address _receiver,\n uint32 _srcEid,\n bytes32 _sender,\n uint64 _nonce\n ) external view returns (bytes32);\n\n function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IMessagingComposer {\n event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);\n event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);\n event LzComposeAlert(\n address indexed from,\n address indexed to,\n address indexed executor,\n bytes32 guid,\n uint16 index,\n uint256 gas,\n uint256 value,\n bytes message,\n bytes extraData,\n bytes reason\n );\n\n function composeQueue(\n address _from,\n address _to,\n bytes32 _guid,\n uint16 _index\n ) external view returns (bytes32 messageHash);\n\n function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;\n\n function lzCompose(\n address _from,\n address _to,\n bytes32 _guid,\n uint16 _index,\n bytes calldata _message,\n bytes calldata _extraData\n ) external payable;\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IMessagingContext {\n function isSendingMessage() external view returns (bool);\n\n function getSendContext() external view returns (uint32 dstEid, address sender);\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { MessagingFee } from \"./ILayerZeroEndpointV2.sol\";\nimport { IMessageLib } from \"./IMessageLib.sol\";\n\nstruct Packet {\n uint64 nonce;\n uint32 srcEid;\n address sender;\n uint32 dstEid;\n bytes32 receiver;\n bytes32 guid;\n bytes message;\n}\n\ninterface ISendLib is IMessageLib {\n function send(\n Packet calldata _packet,\n bytes calldata _options,\n bool _payInLzToken\n ) external returns (MessagingFee memory, bytes memory encodedPacket);\n\n function quote(\n Packet calldata _packet,\n bytes calldata _options,\n bool _payInLzToken\n ) external view returns (MessagingFee memory);\n\n function setTreasury(address _treasury) external;\n\n function withdrawFee(address _to, uint256 _amount) external;\n\n function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nlibrary AddressCast {\n error AddressCast_InvalidSizeForAddress();\n error AddressCast_InvalidAddress();\n\n function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {\n if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();\n result = bytes32(_addressBytes);\n unchecked {\n uint256 offset = 32 - _addressBytes.length;\n result = result >> (offset * 8);\n }\n }\n\n function toBytes32(address _address) internal pure returns (bytes32 result) {\n result = bytes32(uint256(uint160(_address)));\n }\n\n function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {\n if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();\n result = new bytes(_size);\n unchecked {\n uint256 offset = 256 - _size * 8;\n assembly {\n mstore(add(result, 32), shl(offset, _addressBytes32))\n }\n }\n }\n\n function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {\n result = address(uint160(uint256(_addressBytes32)));\n }\n\n function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {\n if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();\n result = address(bytes20(_addressBytes));\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nlibrary CalldataBytesLib {\n function toU8(bytes calldata _bytes, uint256 _start) internal pure returns (uint8) {\n return uint8(_bytes[_start]);\n }\n\n function toU16(bytes calldata _bytes, uint256 _start) internal pure returns (uint16) {\n unchecked {\n uint256 end = _start + 2;\n return uint16(bytes2(_bytes[_start:end]));\n }\n }\n\n function toU32(bytes calldata _bytes, uint256 _start) internal pure returns (uint32) {\n unchecked {\n uint256 end = _start + 4;\n return uint32(bytes4(_bytes[_start:end]));\n }\n }\n\n function toU64(bytes calldata _bytes, uint256 _start) internal pure returns (uint64) {\n unchecked {\n uint256 end = _start + 8;\n return uint64(bytes8(_bytes[_start:end]));\n }\n }\n\n function toU128(bytes calldata _bytes, uint256 _start) internal pure returns (uint128) {\n unchecked {\n uint256 end = _start + 16;\n return uint128(bytes16(_bytes[_start:end]));\n }\n }\n\n function toU256(bytes calldata _bytes, uint256 _start) internal pure returns (uint256) {\n unchecked {\n uint256 end = _start + 32;\n return uint256(bytes32(_bytes[_start:end]));\n }\n }\n\n function toAddr(bytes calldata _bytes, uint256 _start) internal pure returns (address) {\n unchecked {\n uint256 end = _start + 20;\n return address(bytes20(_bytes[_start:end]));\n }\n }\n\n function toB32(bytes calldata _bytes, uint256 _start) internal pure returns (bytes32) {\n unchecked {\n uint256 end = _start + 32;\n return bytes32(_bytes[_start:end]);\n }\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Errors.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nlibrary Errors {\n error LZ_LzTokenUnavailable();\n error LZ_InvalidReceiveLibrary();\n error LZ_InvalidNonce(uint64 nonce);\n error LZ_InvalidArgument();\n error LZ_InvalidExpiry();\n error LZ_InvalidAmount(uint256 required, uint256 supplied);\n error LZ_OnlyRegisteredOrDefaultLib();\n error LZ_OnlyRegisteredLib();\n error LZ_OnlyNonDefaultLib();\n error LZ_Unauthorized();\n error LZ_DefaultSendLibUnavailable();\n error LZ_DefaultReceiveLibUnavailable();\n error LZ_PathNotInitializable();\n error LZ_PathNotVerifiable();\n error LZ_OnlySendLib();\n error LZ_OnlyReceiveLib();\n error LZ_UnsupportedEid();\n error LZ_UnsupportedInterface();\n error LZ_AlreadyRegistered();\n error LZ_SameValue();\n error LZ_InvalidPayloadHash();\n error LZ_PayloadHashNotFound(bytes32 expected, bytes32 actual);\n error LZ_ComposeNotFound(bytes32 expected, bytes32 actual);\n error LZ_ComposeExists();\n error LZ_SendReentrancy();\n error LZ_NotImplemented();\n error LZ_InsufficientFee(\n uint256 requiredNative,\n uint256 suppliedNative,\n uint256 requiredLzToken,\n uint256 suppliedLzToken\n );\n error LZ_ZeroLzTokenFee();\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/GUID.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { AddressCast } from \"./AddressCast.sol\";\n\nlibrary GUID {\n using AddressCast for address;\n\n function generate(\n uint64 _nonce,\n uint32 _srcEid,\n address _sender,\n uint32 _dstEid,\n bytes32 _receiver\n ) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_nonce, _srcEid, _sender.toBytes32(), _dstEid, _receiver));\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Transfer.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary Transfer {\n using SafeERC20 for IERC20;\n\n address internal constant ADDRESS_ZERO = address(0);\n\n error Transfer_NativeFailed(address _to, uint256 _value);\n error Transfer_ToAddressIsZero();\n\n function native(address _to, uint256 _value) internal {\n if (_to == ADDRESS_ZERO) revert Transfer_ToAddressIsZero();\n (bool success, ) = _to.call{ value: _value }(\"\");\n if (!success) revert Transfer_NativeFailed(_to, _value);\n }\n\n function token(address _token, address _to, uint256 _value) internal {\n if (_to == ADDRESS_ZERO) revert Transfer_ToAddressIsZero();\n IERC20(_token).safeTransfer(_to, _value);\n }\n\n function nativeOrToken(address _token, address _to, uint256 _value) internal {\n if (_token == ADDRESS_ZERO) {\n native(_to, _value);\n } else {\n token(_token, _to, _value);\n }\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/BitMaps.sol\npragma solidity ^0.8.20;\n\ntype BitMap256 is uint256;\n\nusing BitMaps for BitMap256 global;\n\nlibrary BitMaps {\n /**\n * @dev Returns whether the bit at `index` is set.\n */\n function get(BitMap256 bitmap, uint8 index) internal pure returns (bool) {\n uint256 mask = 1 << index;\n return BitMap256.unwrap(bitmap) & mask != 0;\n }\n\n /**\n * @dev Sets the bit at `index`.\n */\n function set(BitMap256 bitmap, uint8 index) internal pure returns (BitMap256) {\n uint256 mask = 1 << index;\n return BitMap256.wrap(BitMap256.unwrap(bitmap) | mask);\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/ExecutorOptions.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { CalldataBytesLib } from \"../../libs/CalldataBytesLib.sol\";\n\nlibrary ExecutorOptions {\n using CalldataBytesLib for bytes;\n\n uint8 internal constant WORKER_ID = 1;\n\n uint8 internal constant OPTION_TYPE_LZRECEIVE = 1;\n uint8 internal constant OPTION_TYPE_NATIVE_DROP = 2;\n uint8 internal constant OPTION_TYPE_LZCOMPOSE = 3;\n uint8 internal constant OPTION_TYPE_ORDERED_EXECUTION = 4;\n\n error Executor_InvalidLzReceiveOption();\n error Executor_InvalidNativeDropOption();\n error Executor_InvalidLzComposeOption();\n\n /// @dev decode the next executor option from the options starting from the specified cursor\n /// @param _options [executor_id][executor_option][executor_id][executor_option]...\n /// executor_option = [option_size][option_type][option]\n /// option_size = len(option_type) + len(option)\n /// executor_id: uint8, option_size: uint16, option_type: uint8, option: bytes\n /// @param _cursor the cursor to start decoding from\n /// @return optionType the type of the option\n /// @return option the option of the executor\n /// @return cursor the cursor to start decoding the next executor option\n function nextExecutorOption(\n bytes calldata _options,\n uint256 _cursor\n ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {\n unchecked {\n // skip worker id\n cursor = _cursor + 1;\n\n // read option size\n uint16 size = _options.toU16(cursor);\n cursor += 2;\n\n // read option type\n optionType = _options.toU8(cursor);\n\n // startCursor and endCursor are used to slice the option from _options\n uint256 startCursor = cursor + 1; // skip option type\n uint256 endCursor = cursor + size;\n option = _options[startCursor:endCursor];\n cursor += size;\n }\n }\n\n function decodeLzReceiveOption(bytes calldata _option) internal pure returns (uint128 gas, uint128 value) {\n if (_option.length != 16 && _option.length != 32) revert Executor_InvalidLzReceiveOption();\n gas = _option.toU128(0);\n value = _option.length == 32 ? _option.toU128(16) : 0;\n }\n\n function decodeNativeDropOption(bytes calldata _option) internal pure returns (uint128 amount, bytes32 receiver) {\n if (_option.length != 48) revert Executor_InvalidNativeDropOption();\n amount = _option.toU128(0);\n receiver = _option.toB32(16);\n }\n\n function decodeLzComposeOption(\n bytes calldata _option\n ) internal pure returns (uint16 index, uint128 gas, uint128 value) {\n if (_option.length != 18 && _option.length != 34) revert Executor_InvalidLzComposeOption();\n index = _option.toU16(0);\n gas = _option.toU128(2);\n value = _option.length == 34 ? _option.toU128(18) : 0;\n }\n\n function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value);\n }\n\n function encodeNativeDropOption(uint128 _amount, bytes32 _receiver) internal pure returns (bytes memory) {\n return abi.encodePacked(_amount, _receiver);\n }\n\n function encodeLzComposeOption(uint16 _index, uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_index, _gas) : abi.encodePacked(_index, _gas, _value);\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { Packet } from \"../../interfaces/ISendLib.sol\";\nimport { AddressCast } from \"../../libs/AddressCast.sol\";\n\nlibrary PacketV1Codec {\n using AddressCast for address;\n using AddressCast for bytes32;\n\n uint8 internal constant PACKET_VERSION = 1;\n\n // header (version + nonce + path)\n // version\n uint256 private constant PACKET_VERSION_OFFSET = 0;\n // nonce\n uint256 private constant NONCE_OFFSET = 1;\n // path\n uint256 private constant SRC_EID_OFFSET = 9;\n uint256 private constant SENDER_OFFSET = 13;\n uint256 private constant DST_EID_OFFSET = 45;\n uint256 private constant RECEIVER_OFFSET = 49;\n // payload (guid + message)\n uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)\n uint256 private constant MESSAGE_OFFSET = 113;\n\n function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {\n encodedPacket = abi.encodePacked(\n PACKET_VERSION,\n _packet.nonce,\n _packet.srcEid,\n _packet.sender.toBytes32(),\n _packet.dstEid,\n _packet.receiver,\n _packet.guid,\n _packet.message\n );\n }\n\n function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n PACKET_VERSION,\n _packet.nonce,\n _packet.srcEid,\n _packet.sender.toBytes32(),\n _packet.dstEid,\n _packet.receiver\n );\n }\n\n function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {\n return abi.encodePacked(_packet.guid, _packet.message);\n }\n\n function header(bytes calldata _packet) internal pure returns (bytes calldata) {\n return _packet[0:GUID_OFFSET];\n }\n\n function version(bytes calldata _packet) internal pure returns (uint8) {\n return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));\n }\n\n function nonce(bytes calldata _packet) internal pure returns (uint64) {\n return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));\n }\n\n function srcEid(bytes calldata _packet) internal pure returns (uint32) {\n return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));\n }\n\n function sender(bytes calldata _packet) internal pure returns (bytes32) {\n return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);\n }\n\n function senderAddressB20(bytes calldata _packet) internal pure returns (address) {\n return sender(_packet).toAddress();\n }\n\n function dstEid(bytes calldata _packet) internal pure returns (uint32) {\n return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));\n }\n\n function receiver(bytes calldata _packet) internal pure returns (bytes32) {\n return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);\n }\n\n function receiverB20(bytes calldata _packet) internal pure returns (address) {\n return receiver(_packet).toAddress();\n }\n\n function guid(bytes calldata _packet) internal pure returns (bytes32) {\n return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);\n }\n\n function message(bytes calldata _packet) internal pure returns (bytes calldata) {\n return bytes(_packet[MESSAGE_OFFSET:]);\n }\n\n function payload(bytes calldata _packet) internal pure returns (bytes calldata) {\n return bytes(_packet[GUID_OFFSET:]);\n }\n\n function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {\n return keccak256(payload(_packet));\n }\n}\n" + }, + "@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingContext.sol": { + "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IMessagingContext } from \"./interfaces/IMessagingContext.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\n\n/// this contract acts as a non-reentrancy guard and a source of messaging context\n/// the context includes the remote eid and the sender address\n/// it separates the send and receive context to allow messaging receipts (send back on receive())\nabstract contract MessagingContext is IMessagingContext {\n uint256 private constant NOT_ENTERED = 1;\n uint256 private _sendContext = NOT_ENTERED;\n\n /// @dev the sendContext is set to 8 bytes 0s + 4 bytes eid + 20 bytes sender\n modifier sendContext(uint32 _dstEid, address _sender) {\n if (_sendContext != NOT_ENTERED) revert Errors.LZ_SendReentrancy();\n _sendContext = (uint256(_dstEid) << 160) | uint160(_sender);\n _;\n _sendContext = NOT_ENTERED;\n }\n\n /// @dev returns true if sending message\n function isSendingMessage() public view returns (bool) {\n return _sendContext != NOT_ENTERED;\n }\n\n /// @dev returns (eid, sender) if sending message, (0, 0) otherwise\n function getSendContext() external view returns (uint32, address) {\n return isSendingMessage() ? _getSendContext(_sendContext) : (0, address(0));\n }\n\n function _getSendContext(uint256 _context) internal pure returns (uint32, address) {\n return (uint32(_context >> 160), address(uint160(_context)));\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ILayerZeroEndpointV2 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\n\n/**\n * @title IOAppCore\n */\ninterface IOAppCore {\n // Custom error messages\n error OnlyPeer(uint32 eid, bytes32 sender);\n error NoPeer(uint32 eid);\n error InvalidEndpointCall();\n error InvalidDelegate();\n\n // Event emitted when a peer (OApp) is set for a corresponding endpoint\n event PeerSet(uint32 eid, bytes32 peer);\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n */\n function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);\n\n /**\n * @notice Retrieves the LayerZero endpoint associated with the OApp.\n * @return iEndpoint The LayerZero endpoint as an interface.\n */\n function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);\n\n /**\n * @notice Retrieves the peer (OApp) associated with a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @return peer The peer address (OApp instance) associated with the corresponding endpoint.\n */\n function peers(uint32 _eid) external view returns (bytes32 peer);\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n */\n function setPeer(uint32 _eid, bytes32 _peer) external;\n\n /**\n * @notice Sets the delegate address for the OApp Core.\n * @param _delegate The address of the delegate to be set.\n */\n function setDelegate(address _delegate) external;\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n/**\n * @title IOAppMsgInspector\n * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.\n */\ninterface IOAppMsgInspector {\n // Custom error message for inspection failure\n error InspectionFailed(bytes message, bytes options);\n\n /**\n * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.\n * @param _message The message payload to be inspected.\n * @param _options Additional options or parameters for inspection.\n * @return valid A boolean indicating whether the inspection passed (true) or failed (false).\n *\n * @dev Optionally done as a revert, OR use the boolean provided to handle the failure.\n */\n function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Struct representing enforced option parameters.\n */\nstruct EnforcedOptionParam {\n uint32 eid; // Endpoint ID\n uint16 msgType; // Message Type\n bytes options; // Additional options\n}\n\n/**\n * @title IOAppOptionsType3\n * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.\n */\ninterface IOAppOptionsType3 {\n // Custom error message for invalid options\n error InvalidOptions(bytes options);\n\n // Event emitted when enforced options are set\n event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);\n\n /**\n * @notice Sets enforced options for specific endpoint and message type combinations.\n * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.\n */\n function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;\n\n /**\n * @notice Combines options for a given endpoint and message type.\n * @param _eid The endpoint ID.\n * @param _msgType The OApp message type.\n * @param _extraOptions Additional options passed by the caller.\n * @return options The combination of caller specified options AND enforced options.\n */\n function combineOptions(\n uint32 _eid,\n uint16 _msgType,\n bytes calldata _extraOptions\n ) external view returns (bytes memory options);\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport { ILayerZeroReceiver, Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol\";\n\ninterface IOAppReceiver is ILayerZeroReceiver {\n /**\n * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.\n * @param _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @param _message The lzReceive payload.\n * @param _sender The sender address.\n * @return isSender Is a valid sender.\n *\n * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.\n * @dev The default sender IS the OAppReceiver implementer.\n */\n function isComposeMsgSender(\n Origin calldata _origin,\n bytes calldata _message,\n address _sender\n ) external view returns (bool isSender);\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IOAppOptionsType3, EnforcedOptionParam } from \"../interfaces/IOAppOptionsType3.sol\";\n\n/**\n * @title OAppOptionsType3\n * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.\n */\nabstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {\n uint16 internal constant OPTION_TYPE_3 = 3;\n\n // @dev The \"msgType\" should be defined in the child contract.\n mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;\n\n /**\n * @dev Sets the enforced options for specific endpoint and message type combinations.\n * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.\n * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.\n * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay\n * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().\n */\n function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {\n _setEnforcedOptions(_enforcedOptions);\n }\n\n /**\n * @dev Sets the enforced options for specific endpoint and message type combinations.\n * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.\n *\n * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.\n * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.\n * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay\n * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().\n */\n function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {\n for (uint256 i = 0; i < _enforcedOptions.length; i++) {\n // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.\n _assertOptionsType3(_enforcedOptions[i].options);\n enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;\n }\n\n emit EnforcedOptionSet(_enforcedOptions);\n }\n\n /**\n * @notice Combines options for a given endpoint and message type.\n * @param _eid The endpoint ID.\n * @param _msgType The OAPP message type.\n * @param _extraOptions Additional options passed by the caller.\n * @return options The combination of caller specified options AND enforced options.\n *\n * @dev If there is an enforced lzReceive option:\n * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}\n * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.\n * @dev This presence of duplicated options is handled off-chain in the verifier/executor.\n */\n function combineOptions(\n uint32 _eid,\n uint16 _msgType,\n bytes calldata _extraOptions\n ) public view virtual returns (bytes memory) {\n bytes memory enforced = enforcedOptions[_eid][_msgType];\n\n // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.\n if (enforced.length == 0) return _extraOptions;\n\n // No caller options, return enforced\n if (_extraOptions.length == 0) return enforced;\n\n // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.\n if (_extraOptions.length >= 2) {\n _assertOptionsType3(_extraOptions);\n // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.\n return bytes.concat(enforced, _extraOptions[2:]);\n }\n\n // No valid set of options was found.\n revert InvalidOptions(_extraOptions);\n }\n\n /**\n * @dev Internal function to assert that options are of type 3.\n * @param _options The options to be checked.\n */\n function _assertOptionsType3(bytes memory _options) internal pure virtual {\n uint16 optionsType;\n assembly {\n optionsType := mload(add(_options, 2))\n }\n if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/libs/ReadCodecV1.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nstruct EVMCallRequestV1 {\n uint16 appRequestLabel; // Label identifying the application or type of request (can be use in lzCompute)\n uint32 targetEid; // Target endpoint ID (representing a target blockchain)\n bool isBlockNum; // True if the request = block number, false if timestamp\n uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request\n uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called\n address to; // Address of the target contract on the target chain\n bytes callData; // Calldata for the contract call\n}\n\nstruct EVMCallComputeV1 {\n uint8 computeSetting; // Compute setting (0 = map only, 1 = reduce only, 2 = map reduce)\n uint32 targetEid; // Target endpoint ID (representing a target blockchain)\n bool isBlockNum; // True if the request = block number, false if timestamp\n uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request\n uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called\n address to; // Address of the target contract on the target chain\n}\n\nlibrary ReadCodecV1 {\n using SafeCast for uint256;\n\n uint16 internal constant CMD_VERSION = 1;\n\n uint8 internal constant REQUEST_VERSION = 1;\n uint16 internal constant RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL = 1;\n\n uint8 internal constant COMPUTE_VERSION = 1;\n uint16 internal constant COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL = 1;\n\n error InvalidVersion();\n error InvalidType();\n\n function decode(\n bytes calldata _cmd\n )\n internal\n pure\n returns (uint16 appCmdLabel, EVMCallRequestV1[] memory evmCallRequests, EVMCallComputeV1 memory compute)\n {\n uint256 offset = 0;\n uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2]));\n offset += 2;\n if (cmdVersion != CMD_VERSION) revert InvalidVersion();\n\n appCmdLabel = uint16(bytes2(_cmd[offset:offset + 2]));\n offset += 2;\n\n (evmCallRequests, offset) = decodeRequestsV1(_cmd, offset);\n\n // decode the compute if it exists\n if (offset < _cmd.length) {\n (compute, ) = decodeEVMCallComputeV1(_cmd, offset);\n }\n }\n\n function decodeRequestsV1(\n bytes calldata _cmd,\n uint256 _offset\n ) internal pure returns (EVMCallRequestV1[] memory evmCallRequests, uint256 newOffset) {\n newOffset = _offset;\n uint16 requestCount = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n\n evmCallRequests = new EVMCallRequestV1[](requestCount);\n for (uint16 i = 0; i < requestCount; i++) {\n uint8 requestVersion = uint8(_cmd[newOffset]);\n newOffset += 1;\n if (requestVersion != REQUEST_VERSION) revert InvalidVersion();\n\n uint16 appRequestLabel = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n\n uint16 resolverType = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n\n if (resolverType == RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL) {\n (EVMCallRequestV1 memory request, uint256 nextOffset) = decodeEVMCallRequestV1(\n _cmd,\n newOffset,\n appRequestLabel\n );\n newOffset = nextOffset;\n evmCallRequests[i] = request;\n } else {\n revert InvalidType();\n }\n }\n }\n\n function decodeEVMCallRequestV1(\n bytes calldata _cmd,\n uint256 _offset,\n uint16 _appRequestLabel\n ) internal pure returns (EVMCallRequestV1 memory request, uint256 newOffset) {\n newOffset = _offset;\n request.appRequestLabel = _appRequestLabel;\n\n uint16 requestSize = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n request.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4]));\n newOffset += 4;\n request.isBlockNum = uint8(_cmd[newOffset]) == 1;\n newOffset += 1;\n request.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8]));\n newOffset += 8;\n request.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n request.to = address(bytes20(_cmd[newOffset:newOffset + 20]));\n newOffset += 20;\n uint16 callDataSize = requestSize - 35;\n request.callData = _cmd[newOffset:newOffset + callDataSize];\n newOffset += callDataSize;\n }\n\n function decodeEVMCallComputeV1(\n bytes calldata _cmd,\n uint256 _offset\n ) internal pure returns (EVMCallComputeV1 memory compute, uint256 newOffset) {\n newOffset = _offset;\n uint8 computeVersion = uint8(_cmd[newOffset]);\n newOffset += 1;\n if (computeVersion != COMPUTE_VERSION) revert InvalidVersion();\n uint16 computeType = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n if (computeType != COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL) revert InvalidType();\n\n compute.computeSetting = uint8(_cmd[newOffset]);\n newOffset += 1;\n compute.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4]));\n newOffset += 4;\n compute.isBlockNum = uint8(_cmd[newOffset]) == 1;\n newOffset += 1;\n compute.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8]));\n newOffset += 8;\n compute.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n compute.to = address(bytes20(_cmd[newOffset:newOffset + 20]));\n newOffset += 20;\n }\n\n function decodeCmdAppLabel(bytes calldata _cmd) internal pure returns (uint16) {\n uint256 offset = 0;\n uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2]));\n offset += 2;\n if (cmdVersion != CMD_VERSION) revert InvalidVersion();\n\n return uint16(bytes2(_cmd[offset:offset + 2]));\n }\n\n function decodeRequestV1AppRequestLabel(bytes calldata _request) internal pure returns (uint16) {\n uint256 offset = 0;\n uint8 requestVersion = uint8(_request[offset]);\n offset += 1;\n if (requestVersion != REQUEST_VERSION) revert InvalidVersion();\n\n return uint16(bytes2(_request[offset:offset + 2]));\n }\n\n function encode(\n uint16 _appCmdLabel,\n EVMCallRequestV1[] memory _evmCallRequests,\n EVMCallComputeV1 memory _evmCallCompute\n ) internal pure returns (bytes memory) {\n bytes memory cmd = encode(_appCmdLabel, _evmCallRequests);\n if (_evmCallCompute.targetEid != 0) {\n // if eid is 0, it means no compute\n cmd = appendEVMCallComputeV1(cmd, _evmCallCompute);\n }\n return cmd;\n }\n\n function encode(\n uint16 _appCmdLabel,\n EVMCallRequestV1[] memory _evmCallRequests\n ) internal pure returns (bytes memory) {\n bytes memory cmd = abi.encodePacked(CMD_VERSION, _appCmdLabel, _evmCallRequests.length.toUint16());\n for (uint256 i = 0; i < _evmCallRequests.length; i++) {\n cmd = appendEVMCallRequestV1(cmd, _evmCallRequests[i]);\n }\n return cmd;\n }\n\n // todo: optimize this with Buffer\n function appendEVMCallRequestV1(\n bytes memory _cmd,\n EVMCallRequestV1 memory _request\n ) internal pure returns (bytes memory) {\n bytes memory newCmd = abi.encodePacked(\n _cmd,\n REQUEST_VERSION,\n _request.appRequestLabel,\n RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL,\n (_request.callData.length + 35).toUint16(),\n _request.targetEid\n );\n return\n abi.encodePacked(\n newCmd,\n _request.isBlockNum,\n _request.blockNumOrTimestamp,\n _request.confirmations,\n _request.to,\n _request.callData\n );\n }\n\n function appendEVMCallComputeV1(\n bytes memory _cmd,\n EVMCallComputeV1 memory _compute\n ) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n _cmd,\n COMPUTE_VERSION,\n COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL,\n _compute.computeSetting,\n _compute.targetEid,\n _compute.isBlockNum,\n _compute.blockNumOrTimestamp,\n _compute.confirmations,\n _compute.to\n );\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers\n// solhint-disable-next-line no-unused-import\nimport { OAppSender, MessagingFee, MessagingReceipt } from \"./OAppSender.sol\";\n// @dev Import the 'Origin' so it's exposed to OApp implementers\n// solhint-disable-next-line no-unused-import\nimport { OAppReceiver, Origin } from \"./OAppReceiver.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OApp\n * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.\n */\nabstract contract OApp is OAppSender, OAppReceiver {\n /**\n * @dev Constructor to initialize the OApp with the provided endpoint and owner.\n * @param _endpoint The address of the LOCAL LayerZero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n */\n constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol implementation.\n * @return receiverVersion The version of the OAppReceiver.sol implementation.\n */\n function oAppVersion()\n public\n pure\n virtual\n override(OAppSender, OAppReceiver)\n returns (uint64 senderVersion, uint64 receiverVersion)\n {\n return (SENDER_VERSION, RECEIVER_VERSION);\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IOAppCore, ILayerZeroEndpointV2 } from \"./interfaces/IOAppCore.sol\";\n\n/**\n * @title OAppCore\n * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.\n */\nabstract contract OAppCore is IOAppCore, Ownable {\n // The LayerZero endpoint associated with the given OApp\n ILayerZeroEndpointV2 public immutable endpoint;\n\n // Mapping to store peers associated with corresponding endpoints\n mapping(uint32 eid => bytes32 peer) public peers;\n\n /**\n * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.\n * @param _endpoint The address of the LOCAL Layer Zero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n *\n * @dev The delegate typically should be set as the owner of the contract.\n */\n constructor(address _endpoint, address _delegate) {\n endpoint = ILayerZeroEndpointV2(_endpoint);\n\n if (_delegate == address(0)) revert InvalidDelegate();\n endpoint.setDelegate(_delegate);\n }\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.\n * @dev Set this to bytes32(0) to remove the peer address.\n * @dev Peer is a bytes32 to accommodate non-evm chains.\n */\n function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {\n _setPeer(_eid, _peer);\n }\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n *\n * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.\n * @dev Set this to bytes32(0) to remove the peer address.\n * @dev Peer is a bytes32 to accommodate non-evm chains.\n */\n function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {\n peers[_eid] = _peer;\n emit PeerSet(_eid, _peer);\n }\n\n /**\n * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.\n * ie. the peer is set to bytes32(0).\n * @param _eid The endpoint ID.\n * @return peer The address of the peer associated with the specified endpoint.\n */\n function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {\n bytes32 peer = peers[_eid];\n if (peer == bytes32(0)) revert NoPeer(_eid);\n return peer;\n }\n\n /**\n * @notice Sets the delegate address for the OApp.\n * @param _delegate The address of the delegate to be set.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.\n */\n function setDelegate(address _delegate) public onlyOwner {\n endpoint.setDelegate(_delegate);\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IOAppReceiver, Origin } from \"./interfaces/IOAppReceiver.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OAppReceiver\n * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.\n */\nabstract contract OAppReceiver is IOAppReceiver, OAppCore {\n // Custom error message for when the caller is not the registered endpoint/\n error OnlyEndpoint(address addr);\n\n // @dev The version of the OAppReceiver implementation.\n // @dev Version is bumped when changes are made to this contract.\n uint64 internal constant RECEIVER_VERSION = 2;\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n *\n * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.\n * ie. this is a RECEIVE only OApp.\n * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.\n */\n function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {\n return (0, RECEIVER_VERSION);\n }\n\n /**\n * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.\n * @dev _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @dev _message The lzReceive payload.\n * @param _sender The sender address.\n * @return isSender Is a valid sender.\n *\n * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.\n * @dev The default sender IS the OAppReceiver implementer.\n */\n function isComposeMsgSender(\n Origin calldata /*_origin*/,\n bytes calldata /*_message*/,\n address _sender\n ) public view virtual returns (bool) {\n return _sender == address(this);\n }\n\n /**\n * @notice Checks if the path initialization is allowed based on the provided origin.\n * @param origin The origin information containing the source endpoint and sender address.\n * @return Whether the path has been initialized.\n *\n * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.\n * @dev This defaults to assuming if a peer has been set, its initialized.\n * Can be overridden by the OApp if there is other logic to determine this.\n */\n function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {\n return peers[origin.srcEid] == origin.sender;\n }\n\n /**\n * @notice Retrieves the next nonce for a given source endpoint and sender address.\n * @dev _srcEid The source endpoint ID.\n * @dev _sender The sender address.\n * @return nonce The next nonce.\n *\n * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.\n * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.\n * @dev This is also enforced by the OApp.\n * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.\n */\n function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {\n return 0;\n }\n\n /**\n * @dev Entry point for receiving messages or packets from the endpoint.\n * @param _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @param _guid The unique identifier for the received LayerZero message.\n * @param _message The payload of the received message.\n * @param _executor The address of the executor for the received message.\n * @param _extraData Additional arbitrary data provided by the corresponding executor.\n *\n * @dev Entry point for receiving msg/packet from the LayerZero endpoint.\n */\n function lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) public payable virtual {\n // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.\n if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);\n\n // Ensure that the sender matches the expected peer for the source endpoint.\n if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);\n\n // Call the internal OApp implementation of lzReceive.\n _lzReceive(_origin, _guid, _message, _executor, _extraData);\n }\n\n /**\n * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.\n */\n function _lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual;\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { SafeERC20, IERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { MessagingParams, MessagingFee, MessagingReceipt } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OAppSender\n * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.\n */\nabstract contract OAppSender is OAppCore {\n using SafeERC20 for IERC20;\n\n // Custom error messages\n error NotEnoughNative(uint256 msgValue);\n error LzTokenUnavailable();\n\n // @dev The version of the OAppSender implementation.\n // @dev Version is bumped when changes are made to this contract.\n uint64 internal constant SENDER_VERSION = 1;\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n *\n * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.\n * ie. this is a SEND only OApp.\n * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions\n */\n function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {\n return (SENDER_VERSION, 0);\n }\n\n /**\n * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.\n * @param _dstEid The destination endpoint ID.\n * @param _message The message payload.\n * @param _options Additional options for the message.\n * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.\n * @return fee The calculated MessagingFee for the message.\n * - nativeFee: The native fee for the message.\n * - lzTokenFee: The LZ token fee for the message.\n */\n function _quote(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n bool _payInLzToken\n ) internal view virtual returns (MessagingFee memory fee) {\n return\n endpoint.quote(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),\n address(this)\n );\n }\n\n /**\n * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.\n * @param _dstEid The destination endpoint ID.\n * @param _message The message payload.\n * @param _options Additional options for the message.\n * @param _fee The calculated LayerZero fee for the message.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess fee values sent to the endpoint.\n * @return receipt The receipt for the sent message.\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function _lzSend(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n MessagingFee memory _fee,\n address _refundAddress\n ) internal virtual returns (MessagingReceipt memory receipt) {\n // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.\n uint256 messageValue = _payNative(_fee.nativeFee);\n if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);\n\n return\n // solhint-disable-next-line check-send-result\n endpoint.send{ value: messageValue }(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),\n _refundAddress\n );\n }\n\n /**\n * @dev Internal function to pay the native fee associated with the message.\n * @param _nativeFee The native fee to be paid.\n * @return nativeFee The amount of native currency paid.\n *\n * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,\n * this will need to be overridden because msg.value would contain multiple lzFees.\n * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.\n * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.\n * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.\n */\n function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {\n if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);\n return _nativeFee;\n }\n\n /**\n * @dev Internal function to pay the LZ token fee associated with the message.\n * @param _lzTokenFee The LZ token fee to be paid.\n *\n * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.\n * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().\n */\n function _payLzToken(uint256 _lzTokenFee) internal virtual {\n // @dev Cannot cache the token because it is not immutable in the endpoint.\n address lzToken = endpoint.lzToken();\n if (lzToken == address(0)) revert LzTokenUnavailable();\n\n // Pay LZ token fee by sending tokens to the endpoint.\n IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.\n// solhint-disable-next-line no-unused-import\nimport { InboundPacket, Origin } from \"../libs/Packet.sol\";\n\n/**\n * @title IOAppPreCrimeSimulator Interface\n * @dev Interface for the preCrime simulation functionality in an OApp.\n */\ninterface IOAppPreCrimeSimulator {\n // @dev simulation result used in PreCrime implementation\n error SimulationResult(bytes result);\n error OnlySelf();\n\n /**\n * @dev Emitted when the preCrime contract address is set.\n * @param preCrimeAddress The address of the preCrime contract.\n */\n event PreCrimeSet(address preCrimeAddress);\n\n /**\n * @dev Retrieves the address of the preCrime contract implementation.\n * @return The address of the preCrime contract.\n */\n function preCrime() external view returns (address);\n\n /**\n * @dev Retrieves the address of the OApp contract.\n * @return The address of the OApp contract.\n */\n function oApp() external view returns (address);\n\n /**\n * @dev Sets the preCrime contract address.\n * @param _preCrime The address of the preCrime contract.\n */\n function setPreCrime(address _preCrime) external;\n\n /**\n * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.\n * @param _packets An array of LayerZero InboundPacket objects representing received packets.\n */\n function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;\n\n /**\n * @dev checks if the specified peer is considered 'trusted' by the OApp.\n * @param _eid The endpoint Id to check.\n * @param _peer The peer to check.\n * @return Whether the peer passed is considered 'trusted' by the OApp.\n */\n function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\nstruct PreCrimePeer {\n uint32 eid;\n bytes32 preCrime;\n bytes32 oApp;\n}\n\n// TODO not done yet\ninterface IPreCrime {\n error OnlyOffChain();\n\n // for simulate()\n error PacketOversize(uint256 max, uint256 actual);\n error PacketUnsorted();\n error SimulationFailed(bytes reason);\n\n // for preCrime()\n error SimulationResultNotFound(uint32 eid);\n error InvalidSimulationResult(uint32 eid, bytes reason);\n error CrimeFound(bytes crime);\n\n function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);\n\n function simulate(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues\n ) external payable returns (bytes memory);\n\n function buildSimulationResult() external view returns (bytes memory);\n\n function preCrime(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues,\n bytes[] calldata _simulations\n ) external;\n\n function version() external view returns (uint64 major, uint8 minor);\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/precrime/libs/Packet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { PacketV1Codec } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol\";\n\n/**\n * @title InboundPacket\n * @dev Structure representing an inbound packet received by the contract.\n */\nstruct InboundPacket {\n Origin origin; // Origin information of the packet.\n uint32 dstEid; // Destination endpointId of the packet.\n address receiver; // Receiver address for the packet.\n bytes32 guid; // Unique identifier of the packet.\n uint256 value; // msg.value of the packet.\n address executor; // Executor address for the packet.\n bytes message; // Message payload of the packet.\n bytes extraData; // Additional arbitrary data for the packet.\n}\n\n/**\n * @title PacketDecoder\n * @dev Library for decoding LayerZero packets.\n */\nlibrary PacketDecoder {\n using PacketV1Codec for bytes;\n\n /**\n * @dev Decode an inbound packet from the given packet data.\n * @param _packet The packet data to decode.\n * @return packet An InboundPacket struct representing the decoded packet.\n */\n function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {\n packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());\n packet.dstEid = _packet.dstEid();\n packet.receiver = _packet.receiverB20();\n packet.guid = _packet.guid();\n packet.message = _packet.message();\n }\n\n /**\n * @dev Decode multiple inbound packets from the given packet data and associated message values.\n * @param _packets An array of packet data to decode.\n * @param _packetMsgValues An array of associated message values for each packet.\n * @return packets An array of InboundPacket structs representing the decoded packets.\n */\n function decode(\n bytes[] calldata _packets,\n uint256[] memory _packetMsgValues\n ) internal pure returns (InboundPacket[] memory packets) {\n packets = new InboundPacket[](_packets.length);\n for (uint256 i = 0; i < _packets.length; i++) {\n bytes calldata packet = _packets[i];\n packets[i] = PacketDecoder.decode(packet);\n // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.\n packets[i].value = _packetMsgValues[i];\n }\n }\n}\n" + }, + "@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IPreCrime } from \"./interfaces/IPreCrime.sol\";\nimport { IOAppPreCrimeSimulator, InboundPacket, Origin } from \"./interfaces/IOAppPreCrimeSimulator.sol\";\n\n/**\n * @title OAppPreCrimeSimulator\n * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.\n */\nabstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {\n // The address of the preCrime implementation.\n address public preCrime;\n\n /**\n * @dev Retrieves the address of the OApp contract.\n * @return The address of the OApp contract.\n *\n * @dev The simulator contract is the base contract for the OApp by default.\n * @dev If the simulator is a separate contract, override this function.\n */\n function oApp() external view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev Sets the preCrime contract address.\n * @param _preCrime The address of the preCrime contract.\n */\n function setPreCrime(address _preCrime) public virtual onlyOwner {\n preCrime = _preCrime;\n emit PreCrimeSet(_preCrime);\n }\n\n /**\n * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.\n * @param _packets An array of InboundPacket objects representing received packets to be delivered.\n *\n * @dev WARNING: MUST revert at the end with the simulation results.\n * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,\n * WITHOUT actually executing them.\n */\n function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {\n for (uint256 i = 0; i < _packets.length; i++) {\n InboundPacket calldata packet = _packets[i];\n\n // Ignore packets that are not from trusted peers.\n if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;\n\n // @dev Because a verifier is calling this function, it doesnt have access to executor params:\n // - address _executor\n // - bytes calldata _extraData\n // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().\n // They are instead stubbed to default values, address(0) and bytes(\"\")\n // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,\n // which would cause the revert to be ignored.\n this.lzReceiveSimulate{ value: packet.value }(\n packet.origin,\n packet.guid,\n packet.message,\n packet.executor,\n packet.extraData\n );\n }\n\n // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().\n revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());\n }\n\n /**\n * @dev Is effectively an internal function because msg.sender must be address(this).\n * Allows resetting the call stack for 'internal' calls.\n * @param _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @param _guid The unique identifier of the packet.\n * @param _message The message payload of the packet.\n * @param _executor The executor address for the packet.\n * @param _extraData Additional data for the packet.\n */\n function lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable virtual {\n // @dev Ensure ONLY can be called 'internally'.\n if (msg.sender != address(this)) revert OnlySelf();\n _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);\n }\n\n /**\n * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.\n * @param _origin The origin information.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address from the src chain.\n * - nonce: The nonce of the LayerZero message.\n * @param _guid The GUID of the LayerZero message.\n * @param _message The LayerZero message.\n * @param _executor The address of the off-chain executor.\n * @param _extraData Arbitrary data passed by the msg executor.\n *\n * @dev Enables the preCrime simulator to mock sending lzReceive() messages,\n * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.\n */\n function _lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual;\n\n /**\n * @dev checks if the specified peer is considered 'trusted' by the OApp.\n * @param _eid The endpoint Id to check.\n * @param _peer The peer to check.\n * @return Whether the peer passed is considered 'trusted' by the OApp.\n */\n function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);\n}\n" + }, + "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { MessagingReceipt, MessagingFee } from \"@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\";\n\n/**\n * @dev Struct representing token parameters for the OFT send() operation.\n */\nstruct SendParam {\n uint32 dstEid; // Destination endpoint ID.\n bytes32 to; // Recipient address.\n uint256 amountLD; // Amount to send in local decimals.\n uint256 minAmountLD; // Minimum amount to send in local decimals.\n bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.\n bytes composeMsg; // The composed message for the send() operation.\n bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.\n}\n\n/**\n * @dev Struct representing OFT limit information.\n * @dev These amounts can change dynamically and are up the specific oft implementation.\n */\nstruct OFTLimit {\n uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.\n uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.\n}\n\n/**\n * @dev Struct representing OFT receipt information.\n */\nstruct OFTReceipt {\n uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.\n // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.\n uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.\n}\n\n/**\n * @dev Struct representing OFT fee details.\n * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.\n */\nstruct OFTFeeDetail {\n int256 feeAmountLD; // Amount of the fee in local decimals.\n string description; // Description of the fee.\n}\n\n/**\n * @title IOFT\n * @dev Interface for the OftChain (OFT) token.\n * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.\n * @dev This specific interface ID is '0x02e49c2c'.\n */\ninterface IOFT {\n // Custom error messages\n error InvalidLocalDecimals();\n error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);\n\n // Events\n event OFTSent(\n bytes32 indexed guid, // GUID of the OFT message.\n uint32 dstEid, // Destination Endpoint ID.\n address indexed fromAddress, // Address of the sender on the src chain.\n uint256 amountSentLD, // Amount of tokens sent in local decimals.\n uint256 amountReceivedLD // Amount of tokens received in local decimals.\n );\n event OFTReceived(\n bytes32 indexed guid, // GUID of the OFT message.\n uint32 srcEid, // Source Endpoint ID.\n address indexed toAddress, // Address of the recipient on the dst chain.\n uint256 amountReceivedLD // Amount of tokens received in local decimals.\n );\n\n /**\n * @notice Retrieves interfaceID and the version of the OFT.\n * @return interfaceId The interface ID.\n * @return version The version.\n *\n * @dev interfaceId: This specific interface ID is '0x02e49c2c'.\n * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.\n * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.\n * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\n */\n function oftVersion() external view returns (bytes4 interfaceId, uint64 version);\n\n /**\n * @notice Retrieves the address of the token associated with the OFT.\n * @return token The address of the ERC20 token implementation.\n */\n function token() external view returns (address);\n\n /**\n * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.\n * @return requiresApproval Needs approval of the underlying token implementation.\n *\n * @dev Allows things like wallet implementers to determine integration requirements,\n * without understanding the underlying token implementation.\n */\n function approvalRequired() external view returns (bool);\n\n /**\n * @notice Retrieves the shared decimals of the OFT.\n * @return sharedDecimals The shared decimals of the OFT.\n */\n function sharedDecimals() external view returns (uint8);\n\n /**\n * @notice Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.\n * @param _sendParam The parameters for the send operation.\n * @return limit The OFT limit information.\n * @return oftFeeDetails The details of OFT fees.\n * @return receipt The OFT receipt information.\n */\n function quoteOFT(\n SendParam calldata _sendParam\n ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);\n\n /**\n * @notice Provides a quote for the send() operation.\n * @param _sendParam The parameters for the send() operation.\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\n * @return fee The calculated LayerZero messaging fee from the send() operation.\n *\n * @dev MessagingFee: LayerZero msg fee\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n */\n function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);\n\n /**\n * @notice Executes the send() operation.\n * @param _sendParam The parameters for the send operation.\n * @param _fee The fee information supplied by the caller.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess funds from fees etc. on the src.\n * @return receipt The LayerZero messaging receipt from the send() operation.\n * @return oftReceipt The OFT receipt information.\n *\n * @dev MessagingReceipt: LayerZero msg receipt\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function send(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) external payable returns (MessagingReceipt memory, OFTReceipt memory);\n}\n" + }, + "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nlibrary OFTComposeMsgCodec {\n // Offset constants for decoding composed messages\n uint8 private constant NONCE_OFFSET = 8;\n uint8 private constant SRC_EID_OFFSET = 12;\n uint8 private constant AMOUNT_LD_OFFSET = 44;\n uint8 private constant COMPOSE_FROM_OFFSET = 76;\n\n /**\n * @dev Encodes a OFT composed message.\n * @param _nonce The nonce value.\n * @param _srcEid The source endpoint ID.\n * @param _amountLD The amount in local decimals.\n * @param _composeMsg The composed message.\n * @return _msg The encoded Composed message.\n */\n function encode(\n uint64 _nonce,\n uint32 _srcEid,\n uint256 _amountLD,\n bytes memory _composeMsg // 0x[composeFrom][composeMsg]\n ) internal pure returns (bytes memory _msg) {\n _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);\n }\n\n /**\n * @dev Retrieves the nonce for the composed message.\n * @param _msg The message.\n * @return The nonce value.\n */\n function nonce(bytes calldata _msg) internal pure returns (uint64) {\n return uint64(bytes8(_msg[:NONCE_OFFSET]));\n }\n\n /**\n * @dev Retrieves the source endpoint ID for the composed message.\n * @param _msg The message.\n * @return The source endpoint ID.\n */\n function srcEid(bytes calldata _msg) internal pure returns (uint32) {\n return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));\n }\n\n /**\n * @dev Retrieves the amount in local decimals from the composed message.\n * @param _msg The message.\n * @return The amount in local decimals.\n */\n function amountLD(bytes calldata _msg) internal pure returns (uint256) {\n return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));\n }\n\n /**\n * @dev Retrieves the composeFrom value from the composed message.\n * @param _msg The message.\n * @return The composeFrom value.\n */\n function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {\n return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);\n }\n\n /**\n * @dev Retrieves the composed message.\n * @param _msg The message.\n * @return The composed message.\n */\n function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {\n return _msg[COMPOSE_FROM_OFFSET:];\n }\n\n /**\n * @dev Converts an address to bytes32.\n * @param _addr The address to convert.\n * @return The bytes32 representation of the address.\n */\n function addressToBytes32(address _addr) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(_addr)));\n }\n\n /**\n * @dev Converts bytes32 to an address.\n * @param _b The bytes32 value to convert.\n * @return The address representation of bytes32.\n */\n function bytes32ToAddress(bytes32 _b) internal pure returns (address) {\n return address(uint160(uint256(_b)));\n }\n}\n" + }, + "@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nlibrary OFTMsgCodec {\n // Offset constants for encoding and decoding OFT messages\n uint8 private constant SEND_TO_OFFSET = 32;\n uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;\n\n /**\n * @dev Encodes an OFT LayerZero message.\n * @param _sendTo The recipient address.\n * @param _amountShared The amount in shared decimals.\n * @param _composeMsg The composed message.\n * @return _msg The encoded message.\n * @return hasCompose A boolean indicating whether the message has a composed payload.\n */\n function encode(\n bytes32 _sendTo,\n uint64 _amountShared,\n bytes memory _composeMsg\n ) internal view returns (bytes memory _msg, bool hasCompose) {\n hasCompose = _composeMsg.length > 0;\n // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.\n _msg = hasCompose\n ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)\n : abi.encodePacked(_sendTo, _amountShared);\n }\n\n /**\n * @dev Checks if the OFT message is composed.\n * @param _msg The OFT message.\n * @return A boolean indicating whether the message is composed.\n */\n function isComposed(bytes calldata _msg) internal pure returns (bool) {\n return _msg.length > SEND_AMOUNT_SD_OFFSET;\n }\n\n /**\n * @dev Retrieves the recipient address from the OFT message.\n * @param _msg The OFT message.\n * @return The recipient address.\n */\n function sendTo(bytes calldata _msg) internal pure returns (bytes32) {\n return bytes32(_msg[:SEND_TO_OFFSET]);\n }\n\n /**\n * @dev Retrieves the amount in shared decimals from the OFT message.\n * @param _msg The OFT message.\n * @return The amount in shared decimals.\n */\n function amountSD(bytes calldata _msg) internal pure returns (uint64) {\n return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));\n }\n\n /**\n * @dev Retrieves the composed message from the OFT message.\n * @param _msg The OFT message.\n * @return The composed message.\n */\n function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {\n return _msg[SEND_AMOUNT_SD_OFFSET:];\n }\n\n /**\n * @dev Converts an address to bytes32.\n * @param _addr The address to convert.\n * @return The bytes32 representation of the address.\n */\n function addressToBytes32(address _addr) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(_addr)));\n }\n\n /**\n * @dev Converts bytes32 to an address.\n * @param _b The bytes32 value to convert.\n * @return The address representation of bytes32.\n */\n function bytes32ToAddress(bytes32 _b) internal pure returns (address) {\n return address(uint160(uint256(_b)));\n }\n}\n" + }, + "@layerzerolabs/oft-evm/contracts/OFTCore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { OApp, Origin } from \"@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol\";\nimport { OAppOptionsType3 } from \"@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol\";\nimport { IOAppMsgInspector } from \"@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol\";\n\nimport { OAppPreCrimeSimulator } from \"@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol\";\n\nimport { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from \"./interfaces/IOFT.sol\";\nimport { OFTMsgCodec } from \"./libs/OFTMsgCodec.sol\";\nimport { OFTComposeMsgCodec } from \"./libs/OFTComposeMsgCodec.sol\";\n\n/**\n * @title OFTCore\n * @dev Abstract contract for the OftChain (OFT) token.\n */\nabstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {\n using OFTMsgCodec for bytes;\n using OFTMsgCodec for bytes32;\n\n // @notice Provides a conversion rate when swapping between denominations of SD and LD\n // - shareDecimals == SD == shared Decimals\n // - localDecimals == LD == local decimals\n // @dev Considers that tokens have different decimal amounts on various chains.\n // @dev eg.\n // For a token\n // - locally with 4 decimals --> 1.2345 => uint(12345)\n // - remotely with 2 decimals --> 1.23 => uint(123)\n // - The conversion rate would be 10 ** (4 - 2) = 100\n // @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote,\n // you can only display 1.23 -> uint(123).\n // @dev To preserve the dust that would otherwise be lost on that conversion,\n // we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh\n uint256 public immutable decimalConversionRate;\n\n // @notice Msg types that are used to identify the various OFT operations.\n // @dev This can be extended in child contracts for non-default oft operations\n // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol.\n uint16 public constant SEND = 1;\n uint16 public constant SEND_AND_CALL = 2;\n\n // Address of an optional contract to inspect both 'message' and 'options'\n address public msgInspector;\n event MsgInspectorSet(address inspector);\n\n /**\n * @dev Constructor.\n * @param _localDecimals The decimals of the token on the local chain (this chain).\n * @param _endpoint The address of the LayerZero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n */\n constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) {\n if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals();\n decimalConversionRate = 10 ** (_localDecimals - sharedDecimals());\n }\n\n /**\n * @notice Retrieves interfaceID and the version of the OFT.\n * @return interfaceId The interface ID.\n * @return version The version.\n *\n * @dev interfaceId: This specific interface ID is '0x02e49c2c'.\n * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.\n * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.\n * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\n */\n function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {\n return (type(IOFT).interfaceId, 1);\n }\n\n /**\n * @dev Retrieves the shared decimals of the OFT.\n * @return The shared decimals of the OFT.\n *\n * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap\n * Lowest common decimal denominator between chains.\n * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).\n * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller.\n * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615\n */\n function sharedDecimals() public view virtual returns (uint8) {\n return 6;\n }\n\n /**\n * @dev Sets the message inspector address for the OFT.\n * @param _msgInspector The address of the message inspector.\n *\n * @dev This is an optional contract that can be used to inspect both 'message' and 'options'.\n * @dev Set it to address(0) to disable it, or set it to a contract address to enable it.\n */\n function setMsgInspector(address _msgInspector) public virtual onlyOwner {\n msgInspector = _msgInspector;\n emit MsgInspectorSet(_msgInspector);\n }\n\n /**\n * @notice Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.\n * @param _sendParam The parameters for the send operation.\n * @return oftLimit The OFT limit information.\n * @return oftFeeDetails The details of OFT fees.\n * @return oftReceipt The OFT receipt information.\n */\n function quoteOFT(\n SendParam calldata _sendParam\n )\n external\n view\n virtual\n returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)\n {\n uint256 minAmountLD = 0; // Unused in the default implementation.\n uint256 maxAmountLD = IERC20(this.token()).totalSupply(); // Unused in the default implementation.\n oftLimit = OFTLimit(minAmountLD, maxAmountLD);\n\n // Unused in the default implementation; reserved for future complex fee details.\n oftFeeDetails = new OFTFeeDetail[](0);\n\n // @dev This is the same as the send() operation, but without the actual send.\n // - amountSentLD is the amount in local decimals that would be sent from the sender.\n // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.\n // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.\n (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(\n _sendParam.amountLD,\n _sendParam.minAmountLD,\n _sendParam.dstEid\n );\n oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);\n }\n\n /**\n * @notice Provides a quote for the send() operation.\n * @param _sendParam The parameters for the send() operation.\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\n * @return msgFee The calculated LayerZero messaging fee from the send() operation.\n *\n * @dev MessagingFee: LayerZero msg fee\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n */\n function quoteSend(\n SendParam calldata _sendParam,\n bool _payInLzToken\n ) external view virtual returns (MessagingFee memory msgFee) {\n // @dev mock the amount to receive, this is the same operation used in the send().\n // The quote is as similar as possible to the actual send() operation.\n (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);\n\n // @dev Builds the options and OFT message to quote in the endpoint.\n (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);\n\n // @dev Calculates the LayerZero fee for the send() operation.\n return _quote(_sendParam.dstEid, message, options, _payInLzToken);\n }\n\n /**\n * @dev Executes the send operation.\n * @param _sendParam The parameters for the send operation.\n * @param _fee The calculated fee for the send() operation.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess funds.\n * @return msgReceipt The receipt for the send operation.\n * @return oftReceipt The OFT receipt information.\n *\n * @dev MessagingReceipt: LayerZero msg receipt\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function send(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {\n return _send(_sendParam, _fee, _refundAddress);\n }\n\n /**\n * @dev Internal function to execute the send operation.\n * @param _sendParam The parameters for the send operation.\n * @param _fee The calculated fee for the send() operation.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess funds.\n * @return msgReceipt The receipt for the send operation.\n * @return oftReceipt The OFT receipt information.\n *\n * @dev MessagingReceipt: LayerZero msg receipt\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function _send(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) internal virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {\n // @dev Applies the token transfers regarding this send() operation.\n // - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.\n // - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.\n (uint256 amountSentLD, uint256 amountReceivedLD) = _debit(\n msg.sender,\n _sendParam.amountLD,\n _sendParam.minAmountLD,\n _sendParam.dstEid\n );\n\n // @dev Builds the options and OFT message to quote in the endpoint.\n (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);\n\n // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.\n msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);\n // @dev Formulate the OFT receipt.\n oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);\n\n emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);\n }\n\n /**\n * @dev Internal function to build the message and options.\n * @param _sendParam The parameters for the send() operation.\n * @param _amountLD The amount in local decimals.\n * @return message The encoded message.\n * @return options The encoded options.\n */\n function _buildMsgAndOptions(\n SendParam calldata _sendParam,\n uint256 _amountLD\n ) internal view virtual returns (bytes memory message, bytes memory options) {\n bool hasCompose;\n // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is.\n (message, hasCompose) = OFTMsgCodec.encode(\n _sendParam.to,\n _toSD(_amountLD),\n // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote.\n // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01'\n _sendParam.composeMsg\n );\n // @dev Change the msg type depending if its composed or not.\n uint16 msgType = hasCompose ? SEND_AND_CALL : SEND;\n // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3.\n options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);\n\n // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.\n // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean\n address inspector = msgInspector; // caches the msgInspector to avoid potential double storage read\n if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);\n }\n\n /**\n * @dev Internal function to handle the receive on the LayerZero endpoint.\n * @param _origin The origin information.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address from the src chain.\n * - nonce: The nonce of the LayerZero message.\n * @param _guid The unique identifier for the received LayerZero message.\n * @param _message The encoded message.\n * @dev _executor The address of the executor.\n * @dev _extraData Additional data.\n */\n function _lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address /*_executor*/, // @dev unused in the default implementation.\n bytes calldata /*_extraData*/ // @dev unused in the default implementation.\n ) internal virtual override {\n // @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)\n // Thus everything is bytes32() encoded in flight.\n address toAddress = _message.sendTo().bytes32ToAddress();\n // @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals\n uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);\n\n if (_message.isComposed()) {\n // @dev Proprietary composeMsg format for the OFT.\n bytes memory composeMsg = OFTComposeMsgCodec.encode(\n _origin.nonce,\n _origin.srcEid,\n amountReceivedLD,\n _message.composeMsg()\n );\n\n // @dev Stores the lzCompose payload that will be executed in a separate tx.\n // Standardizes functionality for executing arbitrary contract invocation on some non-evm chains.\n // @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed.\n // @dev The index is used when a OApp needs to compose multiple msgs on lzReceive.\n // For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0.\n endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg);\n }\n\n emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);\n }\n\n /**\n * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.\n * @param _origin The origin information.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address from the src chain.\n * - nonce: The nonce of the LayerZero message.\n * @param _guid The unique identifier for the received LayerZero message.\n * @param _message The LayerZero message.\n * @param _executor The address of the off-chain executor.\n * @param _extraData Arbitrary data passed by the msg executor.\n *\n * @dev Enables the preCrime simulator to mock sending lzReceive() messages,\n * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.\n */\n function _lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual override {\n _lzReceive(_origin, _guid, _message, _executor, _extraData);\n }\n\n /**\n * @dev Check if the peer is considered 'trusted' by the OApp.\n * @param _eid The endpoint ID to check.\n * @param _peer The peer to check.\n * @return Whether the peer passed is considered 'trusted' by the OApp.\n *\n * @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source.\n */\n function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {\n return peers[_eid] == _peer;\n }\n\n /**\n * @dev Internal function to remove dust from the given local decimal amount.\n * @param _amountLD The amount in local decimals.\n * @return amountLD The amount after removing dust.\n *\n * @dev Prevents the loss of dust when moving amounts between chains with different decimals.\n * @dev eg. uint(123) with a conversion rate of 100 becomes uint(100).\n */\n function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) {\n return (_amountLD / decimalConversionRate) * decimalConversionRate;\n }\n\n /**\n * @dev Internal function to convert an amount from shared decimals into local decimals.\n * @param _amountSD The amount in shared decimals.\n * @return amountLD The amount in local decimals.\n */\n function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) {\n return _amountSD * decimalConversionRate;\n }\n\n /**\n * @dev Internal function to convert an amount from local decimals into shared decimals.\n * @param _amountLD The amount in local decimals.\n * @return amountSD The amount in shared decimals.\n */\n function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {\n return uint64(_amountLD / decimalConversionRate);\n }\n\n /**\n * @dev Internal function to mock the amount mutation from a OFT debit() operation.\n * @param _amountLD The amount to send in local decimals.\n * @param _minAmountLD The minimum amount to send in local decimals.\n * @dev _dstEid The destination endpoint ID.\n * @return amountSentLD The amount sent, in local decimals.\n * @return amountReceivedLD The amount to be received on the remote chain, in local decimals.\n *\n * @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.\n */\n function _debitView(\n uint256 _amountLD,\n uint256 _minAmountLD,\n uint32 /*_dstEid*/\n ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {\n // @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.\n amountSentLD = _removeDust(_amountLD);\n // @dev The amount to send is the same as amount received in the default implementation.\n amountReceivedLD = amountSentLD;\n\n // @dev Check for slippage.\n if (amountReceivedLD < _minAmountLD) {\n revert SlippageExceeded(amountReceivedLD, _minAmountLD);\n }\n }\n\n /**\n * @dev Internal function to perform a debit operation.\n * @param _from The address to debit.\n * @param _amountLD The amount to send in local decimals.\n * @param _minAmountLD The minimum amount to send in local decimals.\n * @param _dstEid The destination endpoint ID.\n * @return amountSentLD The amount sent in local decimals.\n * @return amountReceivedLD The amount received in local decimals on the remote.\n *\n * @dev Defined here but are intended to be overriden depending on the OFT implementation.\n * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.\n */\n function _debit(\n address _from,\n uint256 _amountLD,\n uint256 _minAmountLD,\n uint32 _dstEid\n ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD);\n\n /**\n * @dev Internal function to perform a credit operation.\n * @param _to The address to credit.\n * @param _amountLD The amount to credit in local decimals.\n * @param _srcEid The source endpoint ID.\n * @return amountReceivedLD The amount ACTUALLY received in local decimals.\n *\n * @dev Defined here but are intended to be overriden depending on the OFT implementation.\n * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.\n */\n function _credit(\n address _to,\n uint256 _amountLD,\n uint32 _srcEid\n ) internal virtual returns (uint256 amountReceivedLD);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/governance/TimelockController.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../access/AccessControl.sol\";\nimport \"../token/ERC721/IERC721Receiver.sol\";\nimport \"../token/ERC1155/IERC1155Receiver.sol\";\n\n/**\n * @dev Contract module which acts as a timelocked controller. When set as the\n * owner of an `Ownable` smart contract, it enforces a timelock on all\n * `onlyOwner` maintenance operations. This gives time for users of the\n * controlled contract to exit before a potentially dangerous maintenance\n * operation is applied.\n *\n * By default, this contract is self administered, meaning administration tasks\n * have to go through the timelock process. The proposer (resp executor) role\n * is in charge of proposing (resp executing) operations. A common use case is\n * to position this {TimelockController} as the owner of a smart contract, with\n * a multisig or a DAO as the sole proposer.\n *\n * _Available since v3.3._\n */\ncontract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\"TIMELOCK_ADMIN_ROLE\");\n bytes32 public constant PROPOSER_ROLE = keccak256(\"PROPOSER_ROLE\");\n bytes32 public constant EXECUTOR_ROLE = keccak256(\"EXECUTOR_ROLE\");\n bytes32 public constant CANCELLER_ROLE = keccak256(\"CANCELLER_ROLE\");\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\n\n mapping(bytes32 => uint256) private _timestamps;\n uint256 private _minDelay;\n\n /**\n * @dev Emitted when a call is scheduled as part of operation `id`.\n */\n event CallScheduled(\n bytes32 indexed id,\n uint256 indexed index,\n address target,\n uint256 value,\n bytes data,\n bytes32 predecessor,\n uint256 delay\n );\n\n /**\n * @dev Emitted when a call is performed as part of operation `id`.\n */\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\n\n /**\n * @dev Emitted when new proposal is scheduled with non-zero salt.\n */\n event CallSalt(bytes32 indexed id, bytes32 salt);\n\n /**\n * @dev Emitted when operation `id` is cancelled.\n */\n event Cancelled(bytes32 indexed id);\n\n /**\n * @dev Emitted when the minimum delay for future operations is modified.\n */\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\n\n /**\n * @dev Initializes the contract with the following parameters:\n *\n * - `minDelay`: initial minimum delay for operations\n * - `proposers`: accounts to be granted proposer and canceller roles\n * - `executors`: accounts to be granted executor role\n * - `admin`: optional account to be granted admin role; disable with zero address\n *\n * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment\n * without being subject to delay, but this role should be subsequently renounced in favor of\n * administration through timelocked proposals. Previous versions of this contract would assign\n * this admin to the deployer automatically and should be renounced as well.\n */\n constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);\n\n // self administration\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\n\n // optional admin\n if (admin != address(0)) {\n _setupRole(TIMELOCK_ADMIN_ROLE, admin);\n }\n\n // register proposers and cancellers\n for (uint256 i = 0; i < proposers.length; ++i) {\n _setupRole(PROPOSER_ROLE, proposers[i]);\n _setupRole(CANCELLER_ROLE, proposers[i]);\n }\n\n // register executors\n for (uint256 i = 0; i < executors.length; ++i) {\n _setupRole(EXECUTOR_ROLE, executors[i]);\n }\n\n _minDelay = minDelay;\n emit MinDelayChange(0, minDelay);\n }\n\n /**\n * @dev Modifier to make a function callable only by a certain role. In\n * addition to checking the sender's role, `address(0)` 's role is also\n * considered. Granting a role to `address(0)` is equivalent to enabling\n * this role for everyone.\n */\n modifier onlyRoleOrOpenRole(bytes32 role) {\n if (!hasRole(role, address(0))) {\n _checkRole(role, _msgSender());\n }\n _;\n }\n\n /**\n * @dev Contract might receive/hold ETH as part of the maintenance process.\n */\n receive() external payable {}\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns whether an id correspond to a registered operation. This\n * includes both Pending, Ready and Done operations.\n */\n function isOperation(bytes32 id) public view virtual returns (bool) {\n return getTimestamp(id) > 0;\n }\n\n /**\n * @dev Returns whether an operation is pending or not. Note that a \"pending\" operation may also be \"ready\".\n */\n function isOperationPending(bytes32 id) public view virtual returns (bool) {\n return getTimestamp(id) > _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns whether an operation is ready for execution. Note that a \"ready\" operation is also \"pending\".\n */\n function isOperationReady(bytes32 id) public view virtual returns (bool) {\n uint256 timestamp = getTimestamp(id);\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\n }\n\n /**\n * @dev Returns whether an operation is done or not.\n */\n function isOperationDone(bytes32 id) public view virtual returns (bool) {\n return getTimestamp(id) == _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns the timestamp at which an operation becomes ready (0 for\n * unset operations, 1 for done operations).\n */\n function getTimestamp(bytes32 id) public view virtual returns (uint256) {\n return _timestamps[id];\n }\n\n /**\n * @dev Returns the minimum delay for an operation to become valid.\n *\n * This value can be changed by executing an operation that calls `updateDelay`.\n */\n function getMinDelay() public view virtual returns (uint256) {\n return _minDelay;\n }\n\n /**\n * @dev Returns the identifier of an operation containing a single\n * transaction.\n */\n function hashOperation(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32) {\n return keccak256(abi.encode(target, value, data, predecessor, salt));\n }\n\n /**\n * @dev Returns the identifier of an operation containing a batch of\n * transactions.\n */\n function hashOperationBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata payloads,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32) {\n return keccak256(abi.encode(targets, values, payloads, predecessor, salt));\n }\n\n /**\n * @dev Schedule an operation containing a single transaction.\n *\n * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function schedule(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _schedule(id, delay);\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\n if (salt != bytes32(0)) {\n emit CallSalt(id, salt);\n }\n }\n\n /**\n * @dev Schedule an operation containing a batch of transactions.\n *\n * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function scheduleBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata payloads,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == payloads.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\n _schedule(id, delay);\n for (uint256 i = 0; i < targets.length; ++i) {\n emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);\n }\n if (salt != bytes32(0)) {\n emit CallSalt(id, salt);\n }\n }\n\n /**\n * @dev Schedule an operation that is to become valid after a given delay.\n */\n function _schedule(bytes32 id, uint256 delay) private {\n require(!isOperation(id), \"TimelockController: operation already scheduled\");\n require(delay >= getMinDelay(), \"TimelockController: insufficient delay\");\n _timestamps[id] = block.timestamp + delay;\n }\n\n /**\n * @dev Cancel an operation.\n *\n * Requirements:\n *\n * - the caller must have the 'canceller' role.\n */\n function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {\n require(isOperationPending(id), \"TimelockController: operation cannot be cancelled\");\n delete _timestamps[id];\n\n emit Cancelled(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a single transaction.\n *\n * Emits a {CallExecuted} event.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\n // thus any modifications to the operation during reentrancy should be caught.\n // slither-disable-next-line reentrancy-eth\n function execute(\n address target,\n uint256 value,\n bytes calldata payload,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n bytes32 id = hashOperation(target, value, payload, predecessor, salt);\n\n _beforeCall(id, predecessor);\n _execute(target, value, payload);\n emit CallExecuted(id, 0, target, value, payload);\n _afterCall(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a batch of transactions.\n *\n * Emits one {CallExecuted} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,\n // thus any modifications to the operation during reentrancy should be caught.\n // slither-disable-next-line reentrancy-eth\n function executeBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata payloads,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == payloads.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);\n\n _beforeCall(id, predecessor);\n for (uint256 i = 0; i < targets.length; ++i) {\n address target = targets[i];\n uint256 value = values[i];\n bytes calldata payload = payloads[i];\n _execute(target, value, payload);\n emit CallExecuted(id, i, target, value, payload);\n }\n _afterCall(id);\n }\n\n /**\n * @dev Execute an operation's call.\n */\n function _execute(address target, uint256 value, bytes calldata data) internal virtual {\n (bool success, ) = target.call{value: value}(data);\n require(success, \"TimelockController: underlying transaction reverted\");\n }\n\n /**\n * @dev Checks before execution of an operation's calls.\n */\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \"TimelockController: missing dependency\");\n }\n\n /**\n * @dev Checks after execution of an operation's calls.\n */\n function _afterCall(bytes32 id) private {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n _timestamps[id] = _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Changes the minimum timelock duration for future operations.\n *\n * Emits a {MinDelayChange} event.\n *\n * Requirements:\n *\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\n */\n function updateDelay(uint256 newDelay) external virtual {\n require(msg.sender == address(this), \"TimelockController: caller must be timelock\");\n emit MinDelayChange(_minDelay, newDelay);\n _minDelay = newDelay;\n }\n\n /**\n * @dev See {IERC721Receiver-onERC721Received}.\n */\n function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {\n return this.onERC721Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155Received}.\n */\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n /**\n * @dev See {IERC1155Receiver-onERC1155BatchReceived}.\n */\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "@openzeppelin/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is\n * configured to use block numbers, this will return the value at the end of the corresponding block.\n */\n function getPastVotes(address account, uint256 timepoint) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is\n * configured to use block numbers, this will return the value at the end of the corresponding block.\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 timepoint) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1271.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param hash Hash of the data to be signed\n * @param signature Signature byte array associated with _data\n */\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC5267.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.0;\n\ninterface IERC5267 {\n /**\n * @dev MAY be emitted to signal that the domain could have changed.\n */\n event EIP712DomainChanged();\n\n /**\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n * signature.\n */\n function eip712Domain()\n external\n view\n returns (\n bytes1 fields,\n string memory name,\n string memory version,\n uint256 chainId,\n address verifyingContract,\n bytes32 salt,\n uint256[] memory extensions\n );\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC5805.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../governance/utils/IVotes.sol\";\nimport \"./IERC6372.sol\";\n\ninterface IERC5805 is IERC6372, IVotes {}\n" + }, + "@openzeppelin/contracts/interfaces/IERC6372.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol)\n\npragma solidity ^0.8.0;\n\ninterface IERC6372 {\n /**\n * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).\n */\n function clock() external view returns (uint48);\n\n /**\n * @dev Description of the clock\n */\n // solhint-disable-next-line func-name-mixedcase\n function CLOCK_MODE() external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/security/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/cryptography/EIP712.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping(address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) EIP712(name, \"1\") {}\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view virtual override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /**\n * @dev \"Consume a nonce\": return the current value and increment.\n *\n * _Available since v4.1._\n */\n function _useNonce(address owner) internal virtual returns (uint256 current) {\n Counters.Counter storage nonce = _nonces[owner];\n current = nonce.current();\n nonce.increment();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Votes.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ERC20Permit.sol\";\nimport \"../../../interfaces/IERC5805.sol\";\nimport \"../../../utils/math/Math.sol\";\nimport \"../../../utils/math/SafeCast.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\n\n/**\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\n * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.\n *\n * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.\n *\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\n *\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\n *\n * _Available since v4.2._\n */\nabstract contract ERC20Votes is ERC20Permit, IERC5805 {\n struct Checkpoint {\n uint32 fromBlock;\n uint224 votes;\n }\n\n bytes32 private constant _DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n mapping(address => address) private _delegates;\n mapping(address => Checkpoint[]) private _checkpoints;\n Checkpoint[] private _totalSupplyCheckpoints;\n\n /**\n * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).\n */\n function clock() public view virtual override returns (uint48) {\n return SafeCast.toUint48(block.number);\n }\n\n /**\n * @dev Description of the clock\n */\n // solhint-disable-next-line func-name-mixedcase\n function CLOCK_MODE() public view virtual override returns (string memory) {\n // Check that the clock was not modified\n require(clock() == block.number, \"ERC20Votes: broken clock mode\");\n return \"mode=blocknumber&from=default\";\n }\n\n /**\n * @dev Get the `pos`-th checkpoint for `account`.\n */\n function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {\n return _checkpoints[account][pos];\n }\n\n /**\n * @dev Get number of checkpoints for `account`.\n */\n function numCheckpoints(address account) public view virtual returns (uint32) {\n return SafeCast.toUint32(_checkpoints[account].length);\n }\n\n /**\n * @dev Get the address `account` is currently delegating to.\n */\n function delegates(address account) public view virtual override returns (address) {\n return _delegates[account];\n }\n\n /**\n * @dev Gets the current votes balance for `account`\n */\n function getVotes(address account) public view virtual override returns (uint256) {\n uint256 pos = _checkpoints[account].length;\n unchecked {\n return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;\n }\n }\n\n /**\n * @dev Retrieve the number of votes for `account` at the end of `timepoint`.\n *\n * Requirements:\n *\n * - `timepoint` must be in the past\n */\n function getPastVotes(address account, uint256 timepoint) public view virtual override returns (uint256) {\n require(timepoint < clock(), \"ERC20Votes: future lookup\");\n return _checkpointsLookup(_checkpoints[account], timepoint);\n }\n\n /**\n * @dev Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances.\n * It is NOT the sum of all the delegated votes!\n *\n * Requirements:\n *\n * - `timepoint` must be in the past\n */\n function getPastTotalSupply(uint256 timepoint) public view virtual override returns (uint256) {\n require(timepoint < clock(), \"ERC20Votes: future lookup\");\n return _checkpointsLookup(_totalSupplyCheckpoints, timepoint);\n }\n\n /**\n * @dev Lookup a value in a list of (sorted) checkpoints.\n */\n function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 timepoint) private view returns (uint256) {\n // We run a binary search to look for the last (most recent) checkpoint taken before (or at) `timepoint`.\n //\n // Initially we check if the block is recent to narrow the search range.\n // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).\n // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.\n // - If the middle checkpoint is after `timepoint`, we look in [low, mid)\n // - If the middle checkpoint is before or equal to `timepoint`, we look in [mid+1, high)\n // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not\n // out of bounds (in which case we're looking too far in the past and the result is 0).\n // Note that if the latest checkpoint available is exactly for `timepoint`, we end up with an index that is\n // past the end of the array, so we technically don't find a checkpoint after `timepoint`, but it works out\n // the same.\n uint256 length = ckpts.length;\n\n uint256 low = 0;\n uint256 high = length;\n\n if (length > 5) {\n uint256 mid = length - Math.sqrt(length);\n if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n while (low < high) {\n uint256 mid = Math.average(low, high);\n if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n unchecked {\n return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes;\n }\n }\n\n /**\n * @dev Delegate votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) public virtual override {\n _delegate(_msgSender(), delegatee);\n }\n\n /**\n * @dev Delegates votes from signer to `delegatee`\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= expiry, \"ERC20Votes: signature expired\");\n address signer = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\n v,\n r,\n s\n );\n require(nonce == _useNonce(signer), \"ERC20Votes: invalid nonce\");\n _delegate(signer, delegatee);\n }\n\n /**\n * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).\n */\n function _maxSupply() internal view virtual returns (uint224) {\n return type(uint224).max;\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been increased.\n */\n function _mint(address account, uint256 amount) internal virtual override {\n super._mint(account, amount);\n require(totalSupply() <= _maxSupply(), \"ERC20Votes: total supply risks overflowing votes\");\n\n _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been decreased.\n */\n function _burn(address account, uint256 amount) internal virtual override {\n super._burn(account, amount);\n\n _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);\n }\n\n /**\n * @dev Move voting power when tokens are transferred.\n *\n * Emits a {IVotes-DelegateVotesChanged} event.\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual override {\n super._afterTokenTransfer(from, to, amount);\n\n _moveVotingPower(delegates(from), delegates(to), amount);\n }\n\n /**\n * @dev Change delegation for `delegator` to `delegatee`.\n *\n * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.\n */\n function _delegate(address delegator, address delegatee) internal virtual {\n address currentDelegate = delegates(delegator);\n uint256 delegatorBalance = balanceOf(delegator);\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveVotingPower(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _moveVotingPower(address src, address dst, uint256 amount) private {\n if (src != dst && amount > 0) {\n if (src != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);\n emit DelegateVotesChanged(src, oldWeight, newWeight);\n }\n\n if (dst != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);\n emit DelegateVotesChanged(dst, oldWeight, newWeight);\n }\n }\n }\n\n function _writeCheckpoint(\n Checkpoint[] storage ckpts,\n function(uint256, uint256) view returns (uint256) op,\n uint256 delta\n ) private returns (uint256 oldWeight, uint256 newWeight) {\n uint256 pos = ckpts.length;\n\n unchecked {\n Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1);\n\n oldWeight = oldCkpt.votes;\n newWeight = op(oldWeight, delta);\n\n if (pos > 0 && oldCkpt.fromBlock == clock()) {\n _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight);\n } else {\n ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(clock()), votes: SafeCast.toUint224(newWeight)}));\n }\n }\n }\n\n function _add(uint256 a, uint256 b) private pure returns (uint256) {\n return a + b;\n }\n\n function _subtract(uint256 a, uint256 b) private pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n */\n function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) {\n assembly {\n mstore(0, ckpts.slot)\n result.slot := add(keccak256(0, 0x20), pos)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.8;\n\nimport \"./ECDSA.sol\";\nimport \"../ShortStrings.sol\";\nimport \"../../interfaces/IERC5267.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n *\n * _Available since v3.4._\n *\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n */\nabstract contract EIP712 is IERC5267 {\n using ShortStrings for *;\n\n bytes32 private constant _TYPE_HASH =\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _cachedDomainSeparator;\n uint256 private immutable _cachedChainId;\n address private immutable _cachedThis;\n\n bytes32 private immutable _hashedName;\n bytes32 private immutable _hashedVersion;\n\n ShortString private immutable _name;\n ShortString private immutable _version;\n string private _nameFallback;\n string private _versionFallback;\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n _name = name.toShortStringWithFallback(_nameFallback);\n _version = version.toShortStringWithFallback(_versionFallback);\n _hashedName = keccak256(bytes(name));\n _hashedVersion = keccak256(bytes(version));\n\n _cachedChainId = block.chainid;\n _cachedDomainSeparator = _buildDomainSeparator();\n _cachedThis = address(this);\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\n return _cachedDomainSeparator;\n } else {\n return _buildDomainSeparator();\n }\n }\n\n function _buildDomainSeparator() private view returns (bytes32) {\n return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n\n /**\n * @dev See {EIP-5267}.\n *\n * _Available since v4.9._\n */\n function eip712Domain()\n public\n view\n virtual\n override\n returns (\n bytes1 fields,\n string memory name,\n string memory version,\n uint256 chainId,\n address verifyingContract,\n bytes32 salt,\n uint256[] memory extensions\n )\n {\n return (\n hex\"0f\", // 01111\n _name.toStringWithFallback(_nameFallback),\n _version.toStringWithFallback(_versionFallback),\n block.chainid,\n address(this),\n bytes32(0),\n new uint256[](0)\n );\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n return\n (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n isValidERC1271SignatureNow(signer, hash, signature);\n }\n\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n * against the signer smart contract using ERC1271.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidERC1271SignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length >= 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/ShortStrings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)\n\npragma solidity ^0.8.8;\n\nimport \"./StorageSlot.sol\";\n\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\n// | length | 0x BB |\ntype ShortString is bytes32;\n\n/**\n * @dev This library provides functions to convert short memory strings\n * into a `ShortString` type that can be used as an immutable variable.\n *\n * Strings of arbitrary length can be optimized using this library if\n * they are short enough (up to 31 bytes) by packing them with their\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\n * fallback mechanism can be used for every other case.\n *\n * Usage example:\n *\n * ```solidity\n * contract Named {\n * using ShortStrings for *;\n *\n * ShortString private immutable _name;\n * string private _nameFallback;\n *\n * constructor(string memory contractName) {\n * _name = contractName.toShortStringWithFallback(_nameFallback);\n * }\n *\n * function name() external view returns (string memory) {\n * return _name.toStringWithFallback(_nameFallback);\n * }\n * }\n * ```\n */\nlibrary ShortStrings {\n // Used as an identifier for strings longer than 31 bytes.\n bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\n\n error StringTooLong(string str);\n error InvalidShortString();\n\n /**\n * @dev Encode a string of at most 31 chars into a `ShortString`.\n *\n * This will trigger a `StringTooLong` error is the input string is too long.\n */\n function toShortString(string memory str) internal pure returns (ShortString) {\n bytes memory bstr = bytes(str);\n if (bstr.length > 31) {\n revert StringTooLong(str);\n }\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\n }\n\n /**\n * @dev Decode a `ShortString` back to a \"normal\" string.\n */\n function toString(ShortString sstr) internal pure returns (string memory) {\n uint256 len = byteLength(sstr);\n // using `new string(len)` would work locally but is not memory safe.\n string memory str = new string(32);\n /// @solidity memory-safe-assembly\n assembly {\n mstore(str, len)\n mstore(add(str, 0x20), sstr)\n }\n return str;\n }\n\n /**\n * @dev Return the length of a `ShortString`.\n */\n function byteLength(ShortString sstr) internal pure returns (uint256) {\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\n if (result > 31) {\n revert InvalidShortString();\n }\n return result;\n }\n\n /**\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\n */\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\n if (bytes(value).length < 32) {\n return toShortString(value);\n } else {\n StorageSlot.getStringSlot(store).value = value;\n return ShortString.wrap(_FALLBACK_SENTINEL);\n }\n }\n\n /**\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n */\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\n if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {\n return toString(value);\n } else {\n return store;\n }\n }\n\n /**\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n *\n * WARNING: This will return the \"byte length\" of the string. This may not reflect the actual length in terms of\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\n */\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\n if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {\n return byteLength(value);\n } else {\n return bytes(store).length;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n// Solidity does not support splitting import across multiple lines\n// solhint-disable-next-line max-line-length\nimport { IOFT, SendParam, MessagingFee, MessagingReceipt, OFTReceipt } from \"@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol\";\n\n/// @notice Stargate implementation type.\nenum StargateType {\n Pool,\n OFT\n}\n\n/// @notice Ticket data for bus ride.\nstruct Ticket {\n uint72 ticketId;\n bytes passengerBytes;\n}\n\n/// @title Interface for Stargate.\n/// @notice Defines an API for sending tokens to destination chains.\ninterface IStargate is IOFT {\n /// @dev This function is same as `send` in OFT interface but returns the ticket data if in the bus ride mode,\n /// which allows the caller to ride and drive the bus in the same transaction.\n function sendToken(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) external payable returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt, Ticket memory ticket);\n\n /// @notice Returns the Stargate implementation type.\n function stargateType() external pure returns (StargateType);\n}\n" + }, + "contracts/adl/AdlUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"../order/OrderStoreUtils.sol\";\nimport \"../order/OrderEventUtils.sol\";\nimport \"../position/PositionStoreUtils.sol\";\nimport \"../nonce/NonceUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\nimport \"../market/Market.sol\";\nimport \"../market/MarketUtils.sol\";\nimport \"../oracle/IOracle.sol\";\n\n// @title AdlUtils\n// @dev Library to help with auto-deleveraging\n// This is particularly for markets with an index token that is different from\n// the long token\n//\n// For example, if there is a DOGE / USD perp market with ETH as the long token\n// it would be possible for the price of DOGE to increase faster than the price of\n// ETH\n//\n// In this scenario, profitable positions should be closed through ADL to ensure\n// that the system remains fully solvent\nlibrary AdlUtils {\n using SafeCast for int256;\n using Market for Market.Props;\n using Position for Position.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // @dev CreateAdlOrderParams struct used in createAdlOrder to avoid stack\n // too deep errors\n //\n // @param dataStore DataStore\n // @param orderStore OrderStore\n // @param account the account to reduce the position for\n // @param market the position's market\n // @param collateralToken the position's collateralToken\n // @param isLong whether the position is long or short\n // @param sizeDeltaUsd the size to reduce the position by\n struct CreateAdlOrderParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n address account;\n address market;\n address collateralToken;\n bool isLong;\n uint256 sizeDeltaUsd;\n uint256 updatedAtTime;\n }\n\n // @dev Multiple positions may need to be reduced to ensure that the pending\n // profits does not exceed the allowed thresholds\n //\n // This automatic reduction of positions can only be done if the pool is in a state\n // where auto-deleveraging is required\n //\n // This function checks the pending profit state and updates an isAdlEnabled\n // flag to avoid having to repeatedly validate whether auto-deleveraging is required\n //\n // Once the pending profit has been reduced below the threshold this function can\n // be called again to clear the flag\n //\n // The ADL check would be possible to do in AdlHandler.executeAdl as well\n // but with that order keepers could use stale oracle prices to prove that\n // an ADL state is possible\n //\n // Having this function allows any order keeper to disable ADL if prices\n // have updated such that ADL is no longer needed\n //\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param oracle Oracle\n // @param market address of the market to check\n // @param isLong indicates whether to check the long or short side of the market\n function updateAdlState(\n DataStore dataStore,\n EventEmitter eventEmitter,\n IOracle oracle,\n address market,\n bool isLong\n ) external {\n uint256 latestAdlTime = getLatestAdlTime(dataStore, market, isLong);\n\n if (oracle.maxTimestamp() < latestAdlTime) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(oracle.maxTimestamp(), latestAdlTime);\n }\n\n Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market);\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, _market);\n // if the MAX_PNL_FACTOR_FOR_ADL is set to be higher than MAX_PNL_FACTOR_FOR_WITHDRAWALS\n // it is possible for a pool to be in a state where withdrawals and ADL is not allowed\n // this is similar to the case where there is a large amount of open positions relative\n // to the amount of tokens in the pool\n (bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded(\n dataStore,\n _market,\n prices,\n isLong,\n Keys.MAX_PNL_FACTOR_FOR_ADL\n );\n\n setIsAdlEnabled(dataStore, market, isLong, shouldEnableAdl);\n // since the latest ADL at is always updated, an ADL keeper could\n // continually cause the latest ADL time to be updated and prevent\n // ADL orders from being executed, however, this may be preferrable\n // over a case where stale prices could be used by ADL keepers\n // to execute orders\n // as such updating of the ADL time is allowed and it is expected\n // that ADL keepers will keep this time updated so that latest prices\n // will be used for ADL\n setLatestAdlAt(dataStore, market, isLong, Chain.currentTimestamp());\n\n emitAdlStateUpdated(eventEmitter, market, isLong, pnlToPoolFactor, maxPnlFactor, shouldEnableAdl);\n }\n\n // @dev Construct an ADL order\n //\n // A decrease order is used to reduce a profitable position\n //\n // @param params CreateAdlOrderParams\n // @return the key of the created order\n function createAdlOrder(CreateAdlOrderParams memory params) external returns (bytes32) {\n bytes32 positionKey = Position.getPositionKey(params.account, params.market, params.collateralToken, params.isLong);\n Position.Props memory position = PositionStoreUtils.get(params.dataStore, positionKey);\n\n if (params.sizeDeltaUsd > position.sizeInUsd()) {\n revert Errors.InvalidSizeDeltaForAdl(params.sizeDeltaUsd, position.sizeInUsd());\n }\n\n Order.Addresses memory addresses = Order.Addresses(\n params.account, // account\n params.account, // receiver\n params.account, // cancellationReceiver\n CallbackUtils.getSavedCallbackContract(params.dataStore, params.account, params.market), // callbackContract\n address(0), // uiFeeReceiver\n params.market, // market\n position.collateralToken(), // initialCollateralToken\n new address[](0) // swapPath\n );\n\n uint256 lastSrcChainId = params.dataStore.getUint(Keys.positionLastSrcChainId(positionKey));\n\n // no slippage is set for this order, it may be preferrable for ADL orders\n // to be executed, in case of large price impact, the user could be refunded\n // through a protocol fund if required, this amount could later be claimed\n // from the price impact pool, this claiming process should be added if\n // required\n //\n // setting a maximum price impact that will work for majority of cases\n // may also be challenging since the price impact would vary based on the\n // amount of collateral being swapped\n //\n // note that the decreasePositionSwapType should be SwapPnlTokenToCollateralToken\n // because fees are calculated with reference to the collateral token\n // fees are deducted from the output amount if the output token is the same as the\n // collateral token\n // swapping the pnl token to the collateral token helps to ensure fees can be paid\n // using the realized profit\n Order.Numbers memory numbers = Order.Numbers(\n Order.OrderType.MarketDecrease, // orderType\n Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken, // decreasePositionSwapType\n params.sizeDeltaUsd, // sizeDeltaUsd\n 0, // initialCollateralDeltaAmount\n 0, // triggerPrice\n position.isLong() ? 0 : type(uint256).max, // acceptablePrice\n 0, // executionFee\n params.dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT), // callbackGasLimit\n 0, // minOutputAmount\n params.updatedAtTime, // updatedAtTime\n 0, // validFromTime\n lastSrcChainId // srcChainId\n );\n\n Order.Flags memory flags = Order.Flags(\n position.isLong(), // isLong\n lastSrcChainId == 0 , // shouldUnwrapNativeToken\n false, // isFrozen\n false // autoCancel\n );\n\n Order.Props memory order = Order.Props(\n addresses,\n numbers,\n flags,\n new bytes32[](0)\n );\n\n bytes32 key = NonceUtils.getNextKey(params.dataStore);\n OrderStoreUtils.set(params.dataStore, key, order);\n\n OrderEventUtils.emitOrderCreated(params.eventEmitter, key, order);\n\n return key;\n }\n\n // @dev validate if the requested ADL can be executed\n //\n // @param dataStore DataStore\n // @param oracle Oracle\n // @param market address of the market to check\n // @param isLong indicates whether to check the long or short side of the market\n function validateAdl(\n DataStore dataStore,\n IOracle oracle,\n address market,\n bool isLong\n ) external view {\n bool isAdlEnabled = AdlUtils.getIsAdlEnabled(dataStore, market, isLong);\n if (!isAdlEnabled) {\n revert Errors.AdlNotEnabled();\n }\n\n uint256 latestAdlTime = AdlUtils.getLatestAdlTime(dataStore, market, isLong);\n if (oracle.maxTimestamp() < latestAdlTime) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(oracle.maxTimestamp(), latestAdlTime);\n }\n }\n\n // @dev get the latest time at which the ADL flag was updated\n //\n // @param dataStore DataStore\n // @param market address of the market to check\n // @param isLong indicates whether to check the long or short side of the market\n //\n // @return the latest time at which the ADL flag was updated\n function getLatestAdlTime(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.latestAdlAtKey(market, isLong));\n }\n\n // @dev set the latest time at which the ADL flag was updated\n //\n // @param dataStore DataStore\n // @param market address of the market to check\n // @param isLong indicates whether to check the long or short side of the market\n // @param value the latest time value\n //\n // @return the latest time value\n function setLatestAdlAt(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\n return dataStore.setUint(Keys.latestAdlAtKey(market, isLong), value);\n }\n\n // @dev get whether ADL is enabled\n //\n // @param dataStore DataStore\n // @param market address of the market to check\n // @param isLong indicates whether to check the long or short side of the market\n //\n // @return whether ADL is enabled\n function getIsAdlEnabled(DataStore dataStore, address market, bool isLong) internal view returns (bool) {\n return dataStore.getBool(Keys.isAdlEnabledKey(market, isLong));\n }\n\n // @dev set whether ADL is enabled\n //\n // @param dataStore DataStore\n // @param market address of the market to check\n // @param isLong indicates whether to check the long or short side of the market\n // @param value whether ADL is enabled\n //\n // @return whether ADL is enabled\n function setIsAdlEnabled(DataStore dataStore, address market, bool isLong, bool value) internal returns (bool) {\n return dataStore.setBool(Keys.isAdlEnabledKey(market, isLong), value);\n }\n\n // @dev emit ADL state update events\n //\n // @param eventEmitter EventEmitter\n // @param market address of the market for the ADL state update\n // @param isLong indicates the ADL state update is for the long or short side of the market\n // @param pnlToPoolFactor the ratio of PnL to pool value\n // @param maxPnlFactor the max PnL factor\n // @param shouldEnableAdl whether ADL was enabled or disabled\n function emitAdlStateUpdated(\n EventEmitter eventEmitter,\n address market,\n bool isLong,\n int256 pnlToPoolFactor,\n uint256 maxPnlFactor,\n bool shouldEnableAdl\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"pnlToPoolFactor\", pnlToPoolFactor);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"maxPnlFactor\", maxPnlFactor);\n\n eventData.boolItems.initItems(2);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n eventData.boolItems.setItem(1, \"shouldEnableAdl\", shouldEnableAdl);\n\n eventEmitter.emitEventLog1(\n \"AdlStateUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n}\n" + }, + "contracts/bank/Bank.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../token/TokenUtils.sol\";\nimport \"../role/RoleModule.sol\";\n\n// @title Bank\n// @dev Contract to handle storing and transferring of tokens\ncontract Bank is RoleModule {\n using SafeERC20 for IERC20;\n\n DataStore public immutable dataStore;\n\n constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {\n dataStore = _dataStore;\n }\n\n receive() external payable {\n address wnt = TokenUtils.wnt(dataStore);\n if (msg.sender != wnt) {\n revert Errors.InvalidNativeTokenSender(msg.sender);\n }\n }\n\n // @dev transfer tokens from this contract to a receiver\n //\n // @param token the token to transfer\n // @param amount the amount to transfer\n // @param receiver the address to transfer to\n function transferOut(\n address token,\n address receiver,\n uint256 amount\n ) external onlyController {\n _transferOut(token, receiver, amount);\n }\n\n // @dev transfer tokens from this contract to a receiver\n // handles native token transfers as well\n //\n // @param token the token to transfer\n // @param amount the amount to transfer\n // @param receiver the address to transfer to\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\n // before transferring\n function transferOut(\n address token,\n address receiver,\n uint256 amount,\n bool shouldUnwrapNativeToken\n ) external onlyController {\n address wnt = TokenUtils.wnt(dataStore);\n\n if (token == wnt && shouldUnwrapNativeToken) {\n _transferOutNativeToken(token, receiver, amount);\n } else {\n _transferOut(token, receiver, amount);\n }\n }\n\n // @dev transfer native tokens from this contract to a receiver\n //\n // @param token the token to transfer\n // @param amount the amount to transfer\n // @param receiver the address to transfer to\n // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token\n // before transferring\n function transferOutNativeToken(\n address receiver,\n uint256 amount\n ) external onlyController {\n address wnt = TokenUtils.wnt(dataStore);\n _transferOutNativeToken(wnt, receiver, amount);\n }\n\n // @dev transfer tokens from this contract to a receiver\n //\n // @param token the token to transfer\n // @param amount the amount to transfer\n // @param receiver the address to transfer to\n function _transferOut(\n address token,\n address receiver,\n uint256 amount\n ) internal {\n if (receiver == address(this)) {\n revert Errors.SelfTransferNotSupported(receiver);\n }\n\n TokenUtils.transfer(dataStore, token, receiver, amount);\n\n _afterTransferOut(token);\n }\n\n // @dev unwrap wrapped native tokens and transfer the native tokens from\n // this contract to a receiver\n //\n // @param token the token to transfer\n // @param amount the amount to transfer\n // @param receiver the address to transfer to\n function _transferOutNativeToken(\n address token,\n address receiver,\n uint256 amount\n ) internal {\n if (receiver == address(this)) {\n revert Errors.SelfTransferNotSupported(receiver);\n }\n\n TokenUtils.withdrawAndSendNativeToken(\n dataStore,\n token,\n receiver,\n amount\n );\n\n _afterTransferOut(token);\n }\n\n function _afterTransferOut(address /* token */) internal virtual {}\n}\n" + }, + "contracts/bank/StrictBank.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./Bank.sol\";\n\n// @title StrictBank\n// @dev a stricter version of Bank\n//\n// the Bank contract does not have functions to validate the amount of tokens\n// transferred in\n// the Bank contract will mainly assume that safeTransferFrom calls work correctly\n// and that tokens were transferred into it if there was no revert\n//\n// the StrictBank contract keeps track of its internal token balance\n// and uses recordTransferIn to compare its change in balance and return\n// the amount of tokens received\ncontract StrictBank is Bank {\n using SafeERC20 for IERC20;\n\n // used to record token balances to evaluate amounts transferred in\n mapping (address => uint256) public tokenBalances;\n\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\n\n // @dev records a token transfer into the contract\n // @param token the token to record the transfer for\n // @return the amount of tokens transferred in\n function recordTransferIn(address token) external onlyController returns (uint256) {\n return _recordTransferIn(token);\n }\n\n // @dev this can be used to update the tokenBalances in case of token burns\n // or similar balance changes\n // the prevBalance is not validated to be more than the nextBalance as this\n // could allow someone to block this call by transferring into the contract\n // @param token the token to record the burn for\n // @return the new balance\n function syncTokenBalance(address token) external onlyController returns (uint256) {\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\n tokenBalances[token] = nextBalance;\n return nextBalance;\n }\n\n // @dev records a token transfer into the contract\n // @param token the token to record the transfer for\n // @return the amount of tokens transferred in\n function _recordTransferIn(address token) internal returns (uint256) {\n uint256 prevBalance = tokenBalances[token];\n uint256 nextBalance = IERC20(token).balanceOf(address(this));\n tokenBalances[token] = nextBalance;\n\n return nextBalance - prevBalance;\n }\n\n // @dev update the internal balance after tokens have been transferred out\n // this is called from the Bank contract\n // @param token the token that was transferred out\n function _afterTransferOut(address token) internal override {\n tokenBalances[token] = IERC20(token).balanceOf(address(this));\n }\n}\n" + }, + "contracts/callback/CallbackUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\n\nimport \"./IOrderCallbackReceiver.sol\";\nimport \"./IDepositCallbackReceiver.sol\";\nimport \"./IWithdrawalCallbackReceiver.sol\";\nimport \"./IShiftCallbackReceiver.sol\";\nimport \"./IGasFeeCallbackReceiver.sol\";\nimport \"./IGlvDepositCallbackReceiver.sol\";\nimport \"./IGlvWithdrawalCallbackReceiver.sol\";\n\nimport \"../order/OrderEventUtils.sol\";\nimport \"../withdrawal/WithdrawalEventUtils.sol\";\nimport \"../deposit/DepositEventUtils.sol\";\nimport \"../shift/ShiftEventUtils.sol\";\nimport \"../glv/glvDeposit/GlvDepositEventUtils.sol\";\nimport \"../glv/glvWithdrawal/GlvWithdrawalEventUtils.sol\";\n\n// @title CallbackUtils\n// @dev most features require a two step process to complete\n// the user first sends a request transaction, then a second transaction is sent\n// by a keeper to execute the request\n//\n// to allow for better composability with other contracts, a callback contract\n// can be specified to be called after request executions or cancellations\n//\n// in case it is necessary to add \"before\" callbacks, extra care should be taken\n// to ensure that important state cannot be changed during the before callback\n// for example, if an order can be cancelled in the \"before\" callback during\n// order execution, it may lead to an order being executed even though the user\n// was already refunded for its cancellation\n//\n// the details from callback errors are not processed to avoid cases where a malicious\n// callback contract returns a very large value to cause transactions to run out of gas\nlibrary CallbackUtils {\n using Address for address;\n using Deposit for Deposit.Props;\n using Withdrawal for Withdrawal.Props;\n using Shift for Shift.Props;\n using Order for Order.Props;\n using GlvDeposit for GlvDeposit.Props;\n using GlvWithdrawal for GlvWithdrawal.Props;\n\n event AfterDepositExecutionError(bytes32 key, Deposit.Props deposit);\n event AfterDepositCancellationError(bytes32 key, Deposit.Props deposit);\n\n event AfterWithdrawalExecutionError(bytes32 key, Withdrawal.Props withdrawal);\n event AfterWithdrawalCancellationError(bytes32 key, Withdrawal.Props withdrawal);\n\n event AfterShiftExecutionError(bytes32 key, Shift.Props shift);\n event AfterShiftCancellationError(bytes32 key, Shift.Props shift);\n\n event AfterOrderExecutionError(bytes32 key, Order.Props order);\n event AfterOrderCancellationError(bytes32 key, Order.Props order);\n event AfterOrderFrozenError(bytes32 key, Order.Props order);\n\n event AfterGlvDepositExecutionError(bytes32 key, GlvDeposit.Props glvDeposit);\n event AfterGlvDepositCancellationError(bytes32 key, GlvDeposit.Props glvDeposit);\n event AfterGlvWithdrawalExecutionError(bytes32 key, GlvWithdrawal.Props glvWithdrawal);\n event AfterGlvWithdrawalCancellationError(bytes32 key, GlvWithdrawal.Props glvWithdrawal);\n\n // @dev validate that the callbackGasLimit is less than the max specified value\n // this is to prevent callback gas limits which are larger than the max gas limits per block\n // as this would allow for callback contracts that can consume all gas and conditionally cause\n // executions to fail\n // @param dataStore DataStore\n // @param callbackGasLimit the callback gas limit\n function validateCallbackGasLimit(DataStore dataStore, uint256 callbackGasLimit) external view {\n uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT);\n if (callbackGasLimit > maxCallbackGasLimit) {\n revert Errors.MaxCallbackGasLimitExceeded(callbackGasLimit, maxCallbackGasLimit);\n }\n }\n\n function validateGasLeftForCallback(uint256 callbackGasLimit) internal view {\n uint256 gasToBeForwarded = gasleft() / 64 * 63;\n if (gasToBeForwarded < callbackGasLimit) {\n revert Errors.InsufficientGasLeftForCallback(gasToBeForwarded, callbackGasLimit);\n }\n }\n\n function setSavedCallbackContract(DataStore dataStore, address account, address market, address callbackContract) external {\n dataStore.setAddress(Keys.savedCallbackContract(account, market), callbackContract);\n }\n\n function getSavedCallbackContract(DataStore dataStore, address account, address market) external view returns (address) {\n return dataStore.getAddress(Keys.savedCallbackContract(account, market));\n }\n\n function refundExecutionFee(\n DataStore dataStore,\n bytes32 key,\n address callbackContract,\n uint256 refundFeeAmount,\n EventUtils.EventLogData memory eventData\n ) internal returns (bool) {\n if (!isValidCallbackContract(callbackContract)) { return false; }\n\n uint256 gasLimit = dataStore.getUint(Keys.REFUND_EXECUTION_FEE_GAS_LIMIT);\n\n validateGasLeftForCallback(gasLimit);\n\n try IGasFeeCallbackReceiver(callbackContract).refundExecutionFee{ gas: gasLimit, value: refundFeeAmount }(\n key,\n eventData\n ) {\n return true;\n } catch {\n return false;\n }\n }\n\n // @dev called after a deposit execution\n // @param key the key of the deposit\n // @param deposit the deposit that was executed\n function afterDepositExecution(\n bytes32 key,\n Deposit.Props memory deposit,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(deposit.callbackContract())) { return; }\n\n EventUtils.EventLogData memory depositData = DepositEventUtils.createEventData(deposit, Deposit.DepositType.Normal);\n\n validateGasLeftForCallback(deposit.callbackGasLimit());\n\n try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositExecution{ gas: deposit.callbackGasLimit() }(\n key,\n depositData,\n eventData\n ) {\n } catch {\n emit AfterDepositExecutionError(key, deposit);\n }\n }\n\n // @dev called after a deposit cancellation\n // @param key the key of the deposit\n // @param deposit the deposit that was cancelled\n function afterDepositCancellation(\n bytes32 key,\n Deposit.Props memory deposit,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(deposit.callbackContract())) { return; }\n\n EventUtils.EventLogData memory depositData = DepositEventUtils.createEventData(deposit, Deposit.DepositType.Normal);\n\n validateGasLeftForCallback(deposit.callbackGasLimit());\n\n try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositCancellation{ gas: deposit.callbackGasLimit() }(\n key,\n depositData,\n eventData\n ) {\n } catch {\n emit AfterDepositCancellationError(key, deposit);\n }\n }\n\n // @dev called after a withdrawal execution\n // @param key the key of the withdrawal\n // @param withdrawal the withdrawal that was executed\n function afterWithdrawalExecution(\n bytes32 key,\n Withdrawal.Props memory withdrawal,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(withdrawal.callbackContract())) { return; }\n\n EventUtils.EventLogData memory withdrawalData = WithdrawalEventUtils.createEventData(withdrawal, Withdrawal.WithdrawalType.Normal);\n\n validateGasLeftForCallback(withdrawal.callbackGasLimit());\n\n try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalExecution{ gas: withdrawal.callbackGasLimit() }(\n key,\n withdrawalData,\n eventData\n ) {\n } catch {\n emit AfterWithdrawalExecutionError(key, withdrawal);\n }\n }\n\n // @dev called after a withdrawal cancellation\n // @param key the key of the withdrawal\n // @param withdrawal the withdrawal that was cancelled\n function afterWithdrawalCancellation(\n bytes32 key,\n Withdrawal.Props memory withdrawal,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(withdrawal.callbackContract())) { return; }\n\n EventUtils.EventLogData memory withdrawalData = WithdrawalEventUtils.createEventData(withdrawal, Withdrawal.WithdrawalType.Normal);\n\n validateGasLeftForCallback(withdrawal.callbackGasLimit());\n\n try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalCancellation{ gas: withdrawal.callbackGasLimit() }(\n key,\n withdrawalData,\n eventData\n ) {\n } catch {\n emit AfterWithdrawalCancellationError(key, withdrawal);\n }\n }\n\n function afterShiftExecution(\n bytes32 key,\n Shift.Props memory shift,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(shift.callbackContract())) { return; }\n\n EventUtils.EventLogData memory shiftData = ShiftEventUtils.createEventData(shift);\n\n validateGasLeftForCallback(shift.callbackGasLimit());\n\n try IShiftCallbackReceiver(shift.callbackContract()).afterShiftExecution{ gas: shift.callbackGasLimit() }(\n key,\n shiftData,\n eventData\n ) {\n } catch {\n emit AfterShiftExecutionError(key, shift);\n }\n }\n function afterShiftCancellation(\n bytes32 key,\n Shift.Props memory shift,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(shift.callbackContract())) { return; }\n\n EventUtils.EventLogData memory shiftData = ShiftEventUtils.createEventData(shift);\n\n validateGasLeftForCallback(shift.callbackGasLimit());\n\n try IShiftCallbackReceiver(shift.callbackContract()).afterShiftCancellation{ gas: shift.callbackGasLimit() }(\n key,\n shiftData,\n eventData\n ) {\n } catch {\n emit AfterShiftCancellationError(key, shift);\n }\n }\n\n // @dev called after an order execution\n // note that the order.size, order.initialCollateralDeltaAmount and other\n // properties may be updated during execution, the new values may not be\n // updated in the order object for the callback\n // @param key the key of the order\n // @param order the order that was executed\n function afterOrderExecution(\n bytes32 key,\n Order.Props memory order,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(order.callbackContract())) { return; }\n\n EventUtils.EventLogData memory orderData = OrderEventUtils.createEventData(order);\n\n validateGasLeftForCallback(order.callbackGasLimit());\n\n try IOrderCallbackReceiver(order.callbackContract()).afterOrderExecution{ gas: order.callbackGasLimit() }(\n key,\n orderData,\n eventData\n ) {\n } catch {\n emit AfterOrderExecutionError(key, order);\n }\n }\n\n // @dev called after an order cancellation\n // @param key the key of the order\n // @param order the order that was cancelled\n function afterOrderCancellation(\n bytes32 key,\n Order.Props memory order,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(order.callbackContract())) { return; }\n\n EventUtils.EventLogData memory orderData = OrderEventUtils.createEventData(order);\n\n validateGasLeftForCallback(order.callbackGasLimit());\n\n try IOrderCallbackReceiver(order.callbackContract()).afterOrderCancellation{ gas: order.callbackGasLimit() }(\n key,\n orderData,\n eventData\n ) {\n } catch {\n emit AfterOrderCancellationError(key, order);\n }\n }\n\n // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info\n // @param key the key of the order\n // @param order the order that was frozen\n function afterOrderFrozen(\n bytes32 key,\n Order.Props memory order,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(order.callbackContract())) { return; }\n\n EventUtils.EventLogData memory orderData = OrderEventUtils.createEventData(order);\n\n validateGasLeftForCallback(order.callbackGasLimit());\n\n try IOrderCallbackReceiver(order.callbackContract()).afterOrderFrozen{ gas: order.callbackGasLimit() }(\n key,\n orderData,\n eventData\n ) {\n } catch {\n emit AfterOrderFrozenError(key, order);\n }\n }\n\n // @dev called after a glvDeposit execution\n // @param key the key of the glvDeposit\n // @param glvDeposit the glvDeposit that was executed\n function afterGlvDepositExecution(\n bytes32 key,\n GlvDeposit.Props memory glvDeposit,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(glvDeposit.callbackContract())) {\n return;\n }\n\n EventUtils.EventLogData memory glvData = GlvDepositEventUtils.createEventData(glvDeposit);\n\n validateGasLeftForCallback(glvDeposit.callbackGasLimit());\n\n try IGlvDepositCallbackReceiver(glvDeposit.callbackContract()).afterGlvDepositExecution{ gas: glvDeposit.callbackGasLimit() }(\n key,\n glvData,\n eventData\n ) {\n } catch {\n emit AfterGlvDepositExecutionError(key, glvDeposit);\n }\n }\n\n // @dev called after a glvDeposit cancellation\n // @param key the key of the glvDeposit\n // @param glvDeposit the glvDeposit that was cancelled\n function afterGlvDepositCancellation(\n bytes32 key,\n GlvDeposit.Props memory glvDeposit,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(glvDeposit.callbackContract())) { return; }\n\n EventUtils.EventLogData memory glvData = GlvDepositEventUtils.createEventData(glvDeposit);\n\n validateGasLeftForCallback(glvDeposit.callbackGasLimit());\n\n try IGlvDepositCallbackReceiver(glvDeposit.callbackContract()).afterGlvDepositCancellation{ gas: glvDeposit.callbackGasLimit() }(\n key,\n glvData,\n eventData\n ) {\n } catch {\n emit AfterGlvDepositCancellationError(key, glvDeposit);\n }\n }\n\n // @dev called after a glvWithdrawal execution\n // @param key the key of the glvWithdrawal\n // @param glvWithdrawal the glvWithdrawal that was executed\n function afterGlvWithdrawalExecution(\n bytes32 key,\n GlvWithdrawal.Props memory glvWithdrawal,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(glvWithdrawal.callbackContract())) { return; }\n\n EventUtils.EventLogData memory glvData = GlvWithdrawalEventUtils.createEventData(glvWithdrawal);\n\n validateGasLeftForCallback(glvWithdrawal.callbackGasLimit());\n\n try IGlvWithdrawalCallbackReceiver(glvWithdrawal.callbackContract()).afterGlvWithdrawalExecution{ gas: glvWithdrawal.callbackGasLimit() }(\n key,\n glvData,\n eventData\n ) {\n } catch {\n emit AfterGlvWithdrawalExecutionError(key, glvWithdrawal);\n }\n }\n\n // @dev called after a glvWithdrawal cancellation\n // @param key the key of the glvWithdrawal\n // @param glvWithdrawal the glvWithdrawal that was cancelled\n function afterGlvWithdrawalCancellation(\n bytes32 key,\n GlvWithdrawal.Props memory glvWithdrawal,\n EventUtils.EventLogData memory eventData\n ) external {\n if (!isValidCallbackContract(glvWithdrawal.callbackContract())) { return; }\n\n EventUtils.EventLogData memory glvData = GlvWithdrawalEventUtils.createEventData(glvWithdrawal);\n\n validateGasLeftForCallback(glvWithdrawal.callbackGasLimit());\n\n try IGlvWithdrawalCallbackReceiver(glvWithdrawal.callbackContract()).afterGlvWithdrawalCancellation{ gas: glvWithdrawal.callbackGasLimit() }(\n key,\n glvData,\n eventData\n ) {\n } catch {\n emit AfterGlvWithdrawalCancellationError(key, glvWithdrawal);\n }\n }\n\n // @dev validates that the given address is a contract\n // @param callbackContract the contract to call\n function isValidCallbackContract(address callbackContract) public view returns (bool) {\n if (callbackContract == address(0)) { return false; }\n if (!callbackContract.isContract()) { return false; }\n\n return true;\n }\n}\n" + }, + "contracts/callback/IDepositCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\n\n\n// @title IDepositCallbackReceiver\n// @dev interface for a deposit callback contract\ninterface IDepositCallbackReceiver {\n // @dev called after a deposit execution\n // @param key the key of the deposit\n // @param deposit the deposit that was executed\n function afterDepositExecution(bytes32 key, EventUtils.EventLogData memory depositData, EventUtils.EventLogData memory eventData) external;\n\n // @dev called after a deposit cancellation\n // @param key the key of the deposit\n // @param deposit the deposit that was cancelled\n function afterDepositCancellation(bytes32 key, EventUtils.EventLogData memory depositData, EventUtils.EventLogData memory eventData) external;\n}\n" + }, + "contracts/callback/IGasFeeCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\n\ninterface IGasFeeCallbackReceiver {\n function refundExecutionFee(bytes32 key, EventUtils.EventLogData memory eventData) external payable;\n}\n" + }, + "contracts/callback/IGlvDepositCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\n\n// @title IGlvDepositCallbackReceiver\n// @dev interface for a glvDeposit callback contract\ninterface IGlvDepositCallbackReceiver {\n // @dev called after a glvDeposit execution\n // @param key the key of the glvDeposit\n // @param glvDeposit the glvDeposit that was executed\n function afterGlvDepositExecution(\n bytes32 key,\n EventUtils.EventLogData memory glvDepositData,\n EventUtils.EventLogData memory eventData\n ) external;\n\n // @dev called after a glvDeposit cancellation\n // @param key the key of the glvDeposit\n // @param glvDeposit the glvDeposit that was cancelled\n function afterGlvDepositCancellation(\n bytes32 key,\n EventUtils.EventLogData memory glvDepositData,\n EventUtils.EventLogData memory eventData\n ) external;\n}\n" + }, + "contracts/callback/IGlvWithdrawalCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\n\n\n// @title IGlvWithdrawalCallbackReceiver\n// @dev interface for a glvWithdrawal callback contract\ninterface IGlvWithdrawalCallbackReceiver {\n // @dev called after a glvWithdrawal execution\n // @param key the key of the glvWithdrawal\n // @param glvWithdrawal the glvWithdrawal that was executed\n function afterGlvWithdrawalExecution(\n bytes32 key,\n EventUtils.EventLogData memory glvWithdrawalData,\n EventUtils.EventLogData memory eventData\n ) external;\n\n // @dev called after a glvWithdrawal cancellation\n // @param key the key of the glvWithdrawal\n // @param glvWithdrawal the glvWithdrawal that was cancelled\n function afterGlvWithdrawalCancellation(\n bytes32 key,\n EventUtils.EventLogData memory glvWithdrawalData,\n EventUtils.EventLogData memory eventData\n ) external;\n}\n" + }, + "contracts/callback/IOrderCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\nimport \"../order/Order.sol\";\n\n// @title IOrderCallbackReceiver\n// @dev interface for an order callback contract\ninterface IOrderCallbackReceiver {\n // @dev called after an order execution\n // @param key the key of the order\n // @param order the order that was executed\n function afterOrderExecution(bytes32 key, EventUtils.EventLogData memory orderData, EventUtils.EventLogData memory eventData) external;\n\n // @dev called after an order cancellation\n // @param key the key of the order\n // @param order the order that was cancelled\n function afterOrderCancellation(bytes32 key, EventUtils.EventLogData memory order, EventUtils.EventLogData memory eventData) external;\n\n // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info\n // @param key the key of the order\n // @param order the order that was frozen\n function afterOrderFrozen(bytes32 key, EventUtils.EventLogData memory order, EventUtils.EventLogData memory eventData) external;\n}\n" + }, + "contracts/callback/IShiftCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\n\ninterface IShiftCallbackReceiver {\n function afterShiftExecution(bytes32 key, EventUtils.EventLogData memory shiftData, EventUtils.EventLogData memory eventData) external;\n function afterShiftCancellation(bytes32 key, EventUtils.EventLogData memory shiftData, EventUtils.EventLogData memory eventData) external;\n}\n" + }, + "contracts/callback/IWithdrawalCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\n\n// @title IWithdrawalCallbackReceiver\n// @dev interface for a withdrawal callback contract\ninterface IWithdrawalCallbackReceiver {\n // @dev called after a withdrawal execution\n // @param key the key of the withdrawal\n // @param withdrawal the withdrawal that was executed\n function afterWithdrawalExecution(bytes32 key, EventUtils.EventLogData memory withdrawal, EventUtils.EventLogData memory eventData) external;\n\n // @dev called after a withdrawal cancellation\n // @param key the key of the withdrawal\n // @param withdrawal the withdrawal that was cancelled\n function afterWithdrawalCancellation(bytes32 key, EventUtils.EventLogData memory withdrawal, EventUtils.EventLogData memory eventData) external;\n}\n" + }, + "contracts/chain/ArbGasInfo.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title ArbGasInfo\ninterface ArbGasInfo {\n function getCurrentTxL1GasFees() external view returns (uint256);\n}\n" + }, + "contracts/chain/ArbSys.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title ArbSys\n// @dev Globally available variables for Arbitrum may have both an L1 and an L2\n// value, the ArbSys interface is used to retrieve the L2 value\ninterface ArbSys {\n function arbBlockNumber() external view returns (uint256);\n function arbBlockHash(uint256 blockNumber) external view returns (bytes32);\n}\n" + }, + "contracts/chain/Chain.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./ArbSys.sol\";\nimport \"./ArbGasInfo.sol\";\n\n// @title Chain\n// @dev Wrap the calls to retrieve chain variables to handle differences\n// between chain implementations\nlibrary Chain {\n // if the ARBITRUM_CHAIN_ID changes, a new version of this library\n // and contracts depending on it would need to be deployed\n uint256 public constant ARBITRUM_CHAIN_ID = 42161;\n uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;\n\n ArbSys public constant arbSys = ArbSys(address(100));\n ArbGasInfo public constant arbGasInfo = ArbGasInfo(address(108));\n\n // @dev return the current block's timestamp\n // @return the current block's timestamp\n function currentTimestamp() internal view returns (uint256) {\n return block.timestamp;\n }\n\n // @dev return the current block's number\n // @return the current block's number\n function currentBlockNumber() internal view returns (uint256) {\n if (shouldUseArbPrecompiles()) {\n return arbSys.arbBlockNumber();\n }\n\n return block.number;\n }\n\n // @dev return the current block's hash\n // @return the current block's hash\n function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {\n if (shouldUseArbPrecompiles()) {\n return arbSys.arbBlockHash(blockNumber);\n }\n\n return blockhash(blockNumber);\n }\n\n function shouldUseArbPrecompiles() internal view returns (bool) {\n return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;\n }\n\n function getCurrentTxL1GasFees() internal view returns (uint256) {\n if (!shouldUseArbPrecompiles()) {\n return 0;\n }\n return arbGasInfo.getCurrentTxL1GasFees();\n }\n}\n" + }, + "contracts/claim/ClaimEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventUtils.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/Cast.sol\";\n\nlibrary ClaimEventUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.Bytes32Items;\n\n // @dev emit a ClaimFundsDeposited event\n // @param eventEmitter the event emitter\n // @param account the account funds were deposited for\n // @param token the token that was deposited\n // @param distributionId the distribution id that was deposited\n // @param amount the amount that was deposited\n // @param nextAmount the updated total amount for the account\n function emitClaimFundsDeposited(\n EventEmitter eventEmitter,\n address account,\n address token,\n uint256 distributionId,\n uint256 amount,\n uint256 nextAmount\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"token\", token);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"distributionId\", distributionId);\n eventData.uintItems.setItem(1, \"amount\", amount);\n eventData.uintItems.setItem(2, \"nextAmount\", nextAmount);\n\n eventEmitter.emitEventLog2(\"ClaimFundsDeposited\", Cast.toBytes32(account), Cast.toBytes32(token), eventData);\n }\n\n // @dev emit a ClaimFundsWithdrawn event\n // @param eventEmitter the event emitter\n // @param account the account that funds were withdrawn for\n // @param token the token that was withdrawn\n // @param distributionId the distribution id that was withdrawn\n // @param amount the amount that was withdrawn\n // @param receiver the address that received the funds\n function emitClaimFundsWithdrawn(\n EventEmitter eventEmitter,\n address account,\n address token,\n uint256 distributionId,\n uint256 amount,\n address receiver\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"receiver\", receiver);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"distributionId\", distributionId);\n eventData.uintItems.setItem(1, \"amount\", amount);\n\n eventEmitter.emitEventLog2(\"ClaimFundsWithdrawn\", Cast.toBytes32(account), Cast.toBytes32(token), eventData);\n }\n\n // @dev emit a ClaimFundsClaimed event\n // this event is emitted when user claims funds and funds are transferred\n // from the claim vault to the receiver\n // @param eventEmitter the event emitter\n // @param account the account that claimed funds\n // @param receiver the address that received the funds\n // @param token the token that was claimed\n // @param distributionId the distribution id that was claimed\n // @param amount the amount that was claimed\n function emitClaimFundsClaimed(\n EventEmitter eventEmitter,\n address account,\n address receiver,\n address token,\n uint256 distributionId,\n uint256 amount\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"receiver\", receiver);\n eventData.addressItems.setItem(2, \"token\", token);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"distributionId\", distributionId);\n eventData.uintItems.setItem(1, \"amount\", amount);\n\n eventEmitter.emitEventLog2(\"ClaimFundsClaimed\", Cast.toBytes32(account), Cast.toBytes32(token), eventData);\n }\n\n // @dev emit a ClaimFundsTransferred event\n // this event is emitted when funds are transferred from one account to another\n // it affects internal accounting of the claimable funds amount only\n // funds stay inside the claim vault\n // @param eventEmitter the event emitter\n // @param token the token that was transferred\n // @param distributionId the distribution id for the transfer\n // @param fromAccount the account that funds were transferred from\n // @param toAccount the account that funds were transferred to\n // @param amount the amount that was transferred\n // @param nextAmount the updated total amount for the recipient\n function emitClaimFundsTransferred(\n EventEmitter eventEmitter,\n address token,\n uint256 distributionId,\n address fromAccount,\n address toAccount,\n uint256 amount,\n uint256 nextAmount\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"fromAccount\", fromAccount);\n eventData.addressItems.setItem(1, \"toAccount\", toAccount);\n eventData.addressItems.setItem(2, \"token\", token);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"distributionId\", distributionId);\n eventData.uintItems.setItem(1, \"amount\", amount);\n eventData.uintItems.setItem(2, \"nextAmount\", nextAmount);\n\n eventEmitter.emitEventLog2(\n \"ClaimFundsTransferred\",\n Cast.toBytes32(fromAccount),\n Cast.toBytes32(toAccount),\n eventData\n );\n }\n\n // @dev emit a ClaimTermsSet event\n // @param eventEmitter the event emitter\n // @param distributionId the distribution id for the terms\n // @param termsHash the hash of the terms string\n function emitClaimTermsSet(EventEmitter eventEmitter, uint256 distributionId, bytes32 termsHash) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"distributionId\", distributionId);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"termsHash\", termsHash);\n\n eventEmitter.emitEventLog1(\"ClaimTermsSet\", bytes32(distributionId), eventData);\n }\n\n // @dev emit a ClaimTermsRemoved event\n // @param eventEmitter the event emitter\n // @param distributionId the distribution id for the terms that were removed\n function emitClaimTermsRemoved(EventEmitter eventEmitter, uint256 distributionId) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"distributionId\", distributionId);\n\n eventEmitter.emitEventLog1(\"ClaimTermsRemoved\", bytes32(distributionId), eventData);\n }\n}\n" + }, + "contracts/claim/ClaimHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\n\nimport \"../role/RoleModule.sol\";\nimport \"../utils/GlobalReentrancyGuard.sol\";\nimport \"../utils/StringUtils.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../error/Errors.sol\";\nimport \"./ClaimVault.sol\";\nimport \"./ClaimUtils.sol\";\nimport \"./ClaimEventUtils.sol\";\nimport \"../feature/FeatureUtils.sol\";\nimport \"../safe/SafeUtils.sol\";\n\n// @title ClaimHandler\n// @dev Contract for distributing lost funds to users\ncontract ClaimHandler is RoleModule, GlobalReentrancyGuard {\n using Address for address;\n using SafeERC20 for IERC20;\n\n EventEmitter public immutable eventEmitter;\n ClaimVault public immutable claimVault;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n ClaimVault _claimVault\n ) RoleModule(_roleStore) GlobalReentrancyGuard(_dataStore) {\n eventEmitter = _eventEmitter;\n claimVault = _claimVault;\n }\n\n struct WithdrawParam {\n address account;\n uint256 distributionId;\n }\n\n struct ClaimParam {\n address token;\n uint256 distributionId;\n bytes termsSignature;\n string acceptedTerms;\n }\n\n struct TransferClaimParam {\n address token;\n uint256 distributionId;\n address fromAccount;\n address toAccount;\n }\n\n struct TransferClaimCache {\n bytes32 fromAccountKey;\n bytes32 toAccountKey;\n uint256 amount;\n uint256 nextAmount;\n }\n\n // @dev deposit funds for multiple accounts and tokens in batch\n // Rebasing tokens, tokens that change balance on transfer, with token burns, etc are not supported\n // If the distribution requires terms, then `setTerms` must be called before depositing funds\n // @param token the token to deposit\n // @param distributionId the distribution id\n // @param params array of deposit parameters\n function depositFunds(\n address token,\n uint256 distributionId,\n ClaimUtils.DepositParam[] calldata params\n ) external globalNonReentrant onlyClaimAdmin {\n uint256 totalTransferAmount = ClaimUtils.incrementClaims(\n dataStore,\n eventEmitter,\n token,\n distributionId,\n params\n );\n\n IERC20(token).safeTransferFrom(msg.sender, address(claimVault), totalTransferAmount);\n dataStore.incrementUint(Keys.totalClaimableFundsAmountKey(token), totalTransferAmount);\n\n ClaimUtils._validateTotalClaimableFundsAmount(dataStore, token, address(claimVault));\n }\n\n // @dev withdraw funds from the claim vault for multiple accounts in batch\n // this is an admin recovery function used when users cannot access their EOA\n // or when alternative distribution methods are needed. This zeros out user\n // claimable amounts and transfers funds to the specified receiver.\n // @param token the token to withdraw\n // @param params array of withdraw parameters\n // @param receiver the receiver of the funds\n function withdrawFunds(\n address token,\n WithdrawParam[] calldata params,\n address receiver\n ) external globalNonReentrant onlyTimelockMultisig {\n ClaimUtils._validateNonEmptyToken(token);\n _validateNonEmptyReceiver(receiver);\n\n if (params.length == 0) {\n revert Errors.InvalidParams(\"withdraw params length is 0\");\n }\n\n uint256 totalWithdrawnAmount;\n for (uint256 i = 0; i < params.length; i++) {\n WithdrawParam memory param = params[i];\n\n ClaimUtils._validateNonEmptyAccount(param.account);\n ClaimUtils._validateNonZeroDistributionId(param.distributionId);\n\n bytes32 claimableKey = Keys.claimableFundsAmountKey(param.account, token, param.distributionId);\n uint256 amount = dataStore.getUint(claimableKey);\n dataStore.setUint(claimableKey, 0);\n totalWithdrawnAmount += amount;\n\n ClaimEventUtils.emitClaimFundsWithdrawn(\n eventEmitter,\n param.account,\n token,\n param.distributionId,\n amount,\n receiver\n );\n }\n claimVault.transferOut(token, receiver, totalWithdrawnAmount);\n dataStore.decrementUint(Keys.totalClaimableFundsAmountKey(token), totalWithdrawnAmount);\n ClaimUtils._validateTotalClaimableFundsAmount(dataStore, token, address(claimVault));\n }\n\n // @dev transfer claim funds between accounts\n // similar to admin recovery, allows for transferring funds between accounts\n // without the need to withdraw and deposit funds\n // @param token the token to transfer\n // @param params array of transfer parameters\n function transferClaim(\n address token,\n TransferClaimParam[] calldata params\n ) external globalNonReentrant onlyTimelockMultisig {\n if (params.length == 0) {\n revert Errors.InvalidParams(\"transfer params length is 0\");\n }\n ClaimUtils._validateNonEmptyToken(token);\n\n TransferClaimCache memory cache;\n for (uint256 i = 0; i < params.length; i++) {\n TransferClaimParam memory param = params[i];\n\n if (param.fromAccount == param.toAccount) {\n revert Errors.InvalidParams(\"fromAccount and toAccount cannot be the same\");\n }\n\n ClaimUtils._validateNonEmptyAccount(param.fromAccount);\n _validateNonEmptyReceiver(param.toAccount);\n ClaimUtils._validateNonZeroDistributionId(param.distributionId);\n\n cache.fromAccountKey = Keys.claimableFundsAmountKey(param.fromAccount, token, param.distributionId);\n cache.amount = dataStore.getUint(cache.fromAccountKey);\n\n if (cache.amount > 0) {\n dataStore.setUint(cache.fromAccountKey, 0);\n cache.toAccountKey = Keys.claimableFundsAmountKey(param.toAccount, token, param.distributionId);\n cache.nextAmount = dataStore.incrementUint(cache.toAccountKey, cache.amount);\n\n ClaimEventUtils.emitClaimFundsTransferred(\n eventEmitter,\n token,\n param.distributionId,\n param.fromAccount,\n param.toAccount,\n cache.amount,\n cache.nextAmount\n );\n }\n }\n\n ClaimUtils._validateTotalClaimableFundsAmount(dataStore, token, address(claimVault));\n }\n\n // @dev claim funds for the calling account for multiple tokens\n // @param params array of claim parameters\n // @param receiver the receiver of the funds\n function acceptTermsAndClaim(ClaimParam[] calldata params, address receiver) external globalNonReentrant {\n if (params.length == 0) {\n revert Errors.InvalidParams(\"claim params length is 0\");\n }\n _validateNonEmptyReceiver(receiver);\n\n for (uint256 i = 0; i < params.length; i++) {\n ClaimParam memory param = params[i];\n\n FeatureUtils.validateFeature(dataStore, Keys.generalClaimFeatureDisabled(param.distributionId));\n\n ClaimUtils._validateNonEmptyToken(param.token);\n ClaimUtils._validateNonZeroDistributionId(param.distributionId);\n\n _validateTermsSignature(param.distributionId, msg.sender, param.termsSignature, param.acceptedTerms);\n\n bytes32 claimableKey = Keys.claimableFundsAmountKey(msg.sender, param.token, param.distributionId);\n uint256 claimableAmount = dataStore.getUint(claimableKey);\n\n if (claimableAmount == 0) {\n revert Errors.EmptyClaimableAmount(param.token);\n }\n\n dataStore.setUint(claimableKey, 0);\n dataStore.decrementUint(Keys.totalClaimableFundsAmountKey(param.token), claimableAmount);\n\n ClaimEventUtils.emitClaimFundsClaimed(\n eventEmitter,\n msg.sender,\n receiver,\n param.token,\n param.distributionId,\n claimableAmount\n );\n\n claimVault.transferOut(param.token, receiver, claimableAmount);\n\n ClaimUtils._validateTotalClaimableFundsAmount(dataStore, param.token, address(claimVault));\n }\n }\n\n function setTerms(uint256 distributionId, string calldata terms) external globalNonReentrant onlyClaimAdmin {\n ClaimUtils._validateNonZeroDistributionId(distributionId);\n if (bytes(terms).length == 0) {\n revert Errors.InvalidParams(\"terms is empty\");\n }\n\n bytes32 termsHash = keccak256(bytes(terms));\n bytes32 claimTermsBackrefKey = Keys.claimTermsBackrefKey(termsHash);\n uint256 existingDistributionId = dataStore.getUint(claimTermsBackrefKey);\n if (existingDistributionId != 0) {\n revert Errors.DuplicateClaimTerms(existingDistributionId);\n }\n\n dataStore.setUint(claimTermsBackrefKey, distributionId);\n dataStore.setString(Keys.claimTermsKey(distributionId), terms);\n\n ClaimEventUtils.emitClaimTermsSet(eventEmitter, distributionId, termsHash);\n }\n\n function removeTerms(uint256 distributionId) external globalNonReentrant onlyClaimAdmin {\n string memory terms = dataStore.getString(Keys.claimTermsKey(distributionId));\n if (bytes(terms).length == 0) {\n revert Errors.InvalidParams(\"terms not found\");\n }\n\n bytes32 termsHash = keccak256(bytes(terms));\n bytes32 claimTermsBackrefKey = Keys.claimTermsBackrefKey(termsHash);\n dataStore.setUint(claimTermsBackrefKey, 0);\n dataStore.setString(Keys.claimTermsKey(distributionId), \"\");\n\n ClaimEventUtils.emitClaimTermsRemoved(eventEmitter, distributionId);\n }\n\n // @dev get the claimable amount for an account and token\n // @param account the account to check\n // @param token the token to check\n // @return the claimable amount\n function getClaimableAmount(\n address account,\n address token,\n uint256[] calldata distributionIds\n ) external view returns (uint256) {\n uint256 totalClaimableAmount;\n for (uint256 i = 0; i < distributionIds.length; i++) {\n uint256 distributionId = distributionIds[i];\n totalClaimableAmount += dataStore.getUint(Keys.claimableFundsAmountKey(account, token, distributionId));\n }\n return totalClaimableAmount;\n }\n\n // @dev get the total claimable amount for a token\n // @param token the token to check\n // @return the total claimable amount\n function getTotalClaimableAmount(address token) external view returns (uint256) {\n return dataStore.getUint(Keys.totalClaimableFundsAmountKey(token));\n }\n\n // note that signature can be empty here for signing by contracts\n function _validateTermsSignature(\n uint256 distributionId,\n address account,\n bytes memory signature,\n string memory acceptedTerms\n ) internal view {\n string memory terms = dataStore.getString(Keys.claimTermsKey(distributionId));\n if (bytes(terms).length == 0) {\n return;\n }\n\n if (StringUtils.compareStrings(terms, acceptedTerms)) {\n return;\n }\n\n bytes memory message = bytes(string.concat(\n terms,\n \"\\ndistributionId \",\n Strings.toString(distributionId),\n \"\\ncontract \",\n Strings.toHexString(address(this)),\n \"\\nchainId \",\n Strings.toString(block.chainid)\n ));\n\n bytes32 ethSignedMessageHash = ECDSA.toEthSignedMessageHash(message);\n (address recoveredSigner, ECDSA.RecoverError error) = ECDSA.tryRecover(ethSignedMessageHash, signature);\n\n if (error == ECDSA.RecoverError.NoError && recoveredSigner == account) {\n return;\n }\n\n if (!account.isContract()) {\n revert Errors.InvalidClaimTermsSignature(recoveredSigner, account);\n }\n\n bool isValidSignature = SignatureChecker.isValidERC1271SignatureNow(account, ethSignedMessageHash, signature);\n\n if (isValidSignature) { return; }\n\n // if the signature is still not valid, attempt to check signature validation for a safe account\n bytes32 safeMessageHash = SafeUtils.getMessageHash(account, message);\n\n isValidSignature = SignatureChecker.isValidERC1271SignatureNow(account, safeMessageHash, signature);\n\n if (isValidSignature) { return; }\n\n revert Errors.InvalidClaimTermsSignatureForContract(account);\n }\n\n function _validateNonEmptyReceiver(address receiver) internal pure {\n if (receiver == address(0)) {\n revert Errors.EmptyReceiver();\n }\n }\n}\n" + }, + "contracts/claim/ClaimUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n\nimport \"../event/EventEmitter.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../error/Errors.sol\";\nimport \"./ClaimEventUtils.sol\";\n\nlibrary ClaimUtils {\n using SafeERC20 for IERC20;\n\n struct DepositParam {\n address account;\n uint256 amount;\n }\n\n function incrementClaims(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address token,\n uint256 distributionId,\n DepositParam[] calldata params\n ) external returns (uint256) {\n if (params.length == 0) {\n revert Errors.InvalidParams(\"deposit params length is 0\");\n }\n _validateNonEmptyToken(token);\n _validateNonZeroDistributionId(distributionId);\n\n uint256 totalTransferAmount;\n\n for (uint256 i = 0; i < params.length; i++) {\n DepositParam memory param = params[i];\n\n _validateNonEmptyAccount(param.account);\n if (param.amount == 0) {\n revert Errors.EmptyAmount();\n }\n\n uint256 nextAmount = dataStore.incrementUint(\n Keys.claimableFundsAmountKey(param.account, token, distributionId),\n param.amount\n );\n\n totalTransferAmount += param.amount;\n\n ClaimEventUtils.emitClaimFundsDeposited(\n eventEmitter,\n param.account,\n token,\n distributionId,\n param.amount,\n nextAmount\n );\n }\n\n return totalTransferAmount;\n }\n\n function _validateNonZeroDistributionId(uint256 distributionId) internal pure {\n if (distributionId == 0) {\n revert Errors.InvalidParams(\"distributionId is 0\");\n }\n }\n\n function _validateNonEmptyAccount(address account) internal pure {\n if (account == address(0)) {\n revert Errors.EmptyAccount();\n }\n }\n\n function _validateNonEmptyToken(address token) internal pure {\n if (token == address(0)) {\n revert Errors.EmptyToken();\n }\n }\n\n function _validateTotalClaimableFundsAmount(DataStore dataStore, address token, address claimVault) internal view {\n // invariant check\n uint256 totalAmountLeft = dataStore.getUint(Keys.totalClaimableFundsAmountKey(token));\n if (totalAmountLeft > IERC20(token).balanceOf(address(claimVault))) {\n revert Errors.InsufficientFunds(token);\n }\n }\n}\n" + }, + "contracts/claim/ClaimVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/Bank.sol\";\n\n// @title ClaimVault\n// @dev Vault contract for holding claimable funds\ncontract ClaimVault is Bank {\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\n}" + }, + "contracts/config/AutoCancelSyncer.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../role/RoleModule.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/BasicMulticall.sol\";\nimport \"../order/OrderStoreUtils.sol\";\nimport \"../position/PositionStoreUtils.sol\";\nimport \"../order/AutoCancelUtils.sol\";\nimport \"../utils/Cast.sol\";\n\ncontract AutoCancelSyncer is ReentrancyGuard, RoleModule, BasicMulticall {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n using Order for Order.Props;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n function syncAutoCancelOrderListForAccount(address account, uint256 start, uint256 end) external onlyConfigKeeper nonReentrant {\n bytes32[] memory positionKeys = PositionStoreUtils.getAccountPositionKeys(dataStore, account, start, end);\n\n for (uint256 i; i < positionKeys.length; i++) {\n _syncAutoCancelOrderListForPosition(account, positionKeys[i]);\n }\n }\n\n function syncAutoCancelOrderListForPosition(address account, bytes32 positionKey) external onlyConfigKeeper nonReentrant {\n _syncAutoCancelOrderListForPosition(account, positionKey);\n }\n\n function _syncAutoCancelOrderListForPosition(address account, bytes32 positionKey) internal {\n bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey);\n\n for (uint256 j; j < orderKeys.length; j++) {\n bytes32 orderKey = orderKeys[j];\n Order.Props memory order = OrderStoreUtils.get(dataStore, orderKey);\n\n if (order.account() == address(0) || (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0)) {\n AutoCancelUtils.removeAutoCancelOrderKey(dataStore, positionKey, orderKey);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"positionKey\", positionKey);\n eventData.bytes32Items.setItem(1, \"orderKey\", orderKey);\n eventEmitter.emitEventLog1(\n \"ConfigSyncAutoCancelOrderList\",\n Cast.toBytes32(account),\n eventData\n );\n }\n }\n }\n}\n" + }, + "contracts/config/Config.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../data/Keys2.sol\";\nimport \"../role/RoleModule.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/BasicMulticall.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../utils/Cast.sol\";\nimport \"../market/MarketUtils.sol\";\n\nimport \"./ConfigUtils.sol\";\n\n// @title Config\ncontract Config is ReentrancyGuard, RoleModule, BasicMulticall {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n // @dev the base keys that can be set\n mapping (bytes32 => bool) public allowedBaseKeys;\n // @dev the limited base keys that can be set\n mapping (bytes32 => bool) public allowedLimitedBaseKeys;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n\n _initAllowedBaseKeys();\n _initAllowedLimitedBaseKeys();\n }\n\n modifier onlyKeeper() {\n if (\n !roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER) &&\n !roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)\n ) {\n revert Errors.Unauthorized(msg.sender, \"LIMITED / CONFIG KEEPER\");\n }\n\n _;\n }\n\n function initOracleProviderForToken(address oracle, address token, address provider) external onlyConfigKeeper nonReentrant {\n if (token == address(0)) {\n revert Errors.EmptyToken();\n }\n\n if (dataStore.getAddress(Keys.oracleProviderForTokenKey(oracle, token)) != address(0)) {\n revert Errors.OracleProviderAlreadyExistsForToken(oracle, token);\n }\n\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(provider))) {\n revert Errors.InvalidOracleProvider(provider);\n }\n\n dataStore.setAddress(Keys.oracleProviderForTokenKey(oracle, token), provider);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"oracle\", oracle);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"provider\", provider);\n eventEmitter.emitEventLog(\n \"InitOracleProviderForToken\",\n eventData\n );\n }\n\n function setOracleProviderForToken(address oracle, address token, address provider) external onlyConfigKeeper nonReentrant {\n if (token == address(0)) {\n revert Errors.EmptyToken();\n }\n\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(provider))) {\n revert Errors.InvalidOracleProvider(provider);\n }\n\n if (Chain.currentTimestamp() - dataStore.getUint(Keys.oracleProviderUpdatedAt(token, provider))\n < dataStore.getUint(Keys.ORACLE_PROVIDER_MIN_CHANGE_DELAY)) {\n revert Errors.OracleProviderMinChangeDelayNotYetPassed(token, provider);\n }\n\n dataStore.setUint(Keys.oracleProviderUpdatedAt(token, provider), Chain.currentTimestamp());\n dataStore.setAddress(Keys.oracleProviderForTokenKey(oracle, token), provider);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"oracle\", oracle);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"provider\", provider);\n eventEmitter.emitEventLog(\n \"SetOracleProviderForToken\",\n eventData\n );\n }\n\n function initOracleConfig(\n ConfigUtils.InitOracleConfigParams memory params\n ) external onlyConfigKeeper nonReentrant {\n ConfigUtils.initOracleConfig(\n dataStore,\n eventEmitter,\n params\n );\n }\n\n function setClaimableCollateralFactorForTime(\n address market,\n address token,\n uint256 timeKey,\n uint256 factor\n ) external onlyConfigKeeper nonReentrant {\n ConfigUtils.setClaimableCollateralFactorForTime(\n dataStore,\n eventEmitter,\n market,\n token,\n timeKey,\n factor\n );\n }\n\n function setClaimableCollateralFactorForAccount(\n address market,\n address token,\n uint256 timeKey,\n address account,\n uint256 factor\n ) external onlyConfigKeeper nonReentrant {\n ConfigUtils.setClaimableCollateralFactorForAccount(\n dataStore,\n eventEmitter,\n market,\n token,\n timeKey,\n account,\n factor\n );\n }\n\n function setClaimableCollateralReductionFactorForAccount(\n address market,\n address token,\n uint256 timeKey,\n address account,\n uint256 factor\n ) external onlyConfigKeeper nonReentrant {\n ConfigUtils.setClaimableCollateralReductionFactorForAccount(\n dataStore,\n eventEmitter,\n market,\n token,\n timeKey,\n account,\n factor\n );\n }\n\n function setPositionImpactDistributionRate(\n address market,\n uint256 minPositionImpactPoolAmount,\n uint256 positionImpactPoolDistributionRate\n ) external onlyConfigKeeper nonReentrant {\n ConfigUtils.setPositionImpactDistributionRate(\n dataStore,\n eventEmitter,\n market,\n minPositionImpactPoolAmount,\n positionImpactPoolDistributionRate\n );\n }\n\n // @dev set a bool value\n // @param baseKey the base key of the value to set\n // @param data the additional data to be combined with the base key\n // @param value the bool value\n function setBool(bytes32 baseKey, bytes memory data, bool value) external onlyKeeper nonReentrant {\n _validateKey(baseKey);\n\n bytes32 fullKey = Keys.getFullKey(baseKey, data);\n\n dataStore.setBool(fullKey, value);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"baseKey\", baseKey);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"data\", data);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"value\", value);\n\n eventEmitter.emitEventLog1(\n \"SetBool\",\n baseKey,\n eventData\n );\n }\n\n // @dev set an address value\n // @param baseKey the base key of the value to set\n // @param data the additional data to be combined with the base key\n // @param value the address value\n function setAddress(bytes32 baseKey, bytes memory data, address value) external onlyKeeper nonReentrant {\n _validateKey(baseKey);\n\n bytes32 fullKey = Keys.getFullKey(baseKey, data);\n\n dataStore.setAddress(fullKey, value);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"baseKey\", baseKey);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"data\", data);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"value\", value);\n\n eventEmitter.emitEventLog1(\n \"SetAddress\",\n baseKey,\n eventData\n );\n }\n\n // @dev set a bytes32 value\n // @param baseKey the base key of the value to set\n // @param data the additional data to be combined with the base key\n // @param value the bytes32 value\n function setBytes32(bytes32 baseKey, bytes memory data, bytes32 value) external onlyKeeper nonReentrant {\n _validateKey(baseKey);\n\n bytes32 fullKey = Keys.getFullKey(baseKey, data);\n\n dataStore.setBytes32(fullKey, value);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"baseKey\", baseKey);\n eventData.bytes32Items.setItem(1, \"value\", value);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"data\", data);\n\n eventEmitter.emitEventLog1(\n \"SetBytes32\",\n baseKey,\n eventData\n );\n }\n\n // @dev set a uint256 value\n // @param basekey the base key of the value to set\n // @param data the additional data to be combined with the base key\n // @param value the uint256 value\n function setUint(bytes32 baseKey, bytes memory data, uint256 value) external onlyKeeper nonReentrant {\n _validateKey(baseKey);\n\n bytes32 fullKey = Keys.getFullKey(baseKey, data);\n\n ConfigUtils.validateRange(\n dataStore,\n baseKey,\n data,\n value\n );\n\n dataStore.setUint(fullKey, value);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"baseKey\", baseKey);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"data\", data);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"value\", value);\n\n eventEmitter.emitEventLog1(\n \"SetUint\",\n baseKey,\n eventData\n );\n }\n\n // @dev set an int256 value\n // @param basekey the base key of the value to set\n // @param data the additional data to be combined with the base key\n // @param value the int256 value\n function setInt(bytes32 baseKey, bytes memory data, int256 value) external onlyKeeper nonReentrant {\n _validateKey(baseKey);\n\n bytes32 fullKey = Keys.getFullKey(baseKey, data);\n\n dataStore.setInt(fullKey, value);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"baseKey\", baseKey);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"data\", data);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"value\", value);\n\n eventEmitter.emitEventLog1(\n \"SetInt\",\n baseKey,\n eventData\n );\n }\n\n // @dev initialize the allowed base keys\n function _initAllowedBaseKeys() internal {\n allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS] = true;\n allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD] = true;\n allowedBaseKeys[Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION] = true;\n\n allowedBaseKeys[Keys.IS_MARKET_DISABLED] = true;\n\n allowedBaseKeys[Keys.MAX_SWAP_PATH_LENGTH] = true;\n allowedBaseKeys[Keys.MAX_CALLBACK_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.REFUND_EXECUTION_FEE_GAS_LIMIT] = true;\n\n allowedBaseKeys[Keys.MIN_POSITION_SIZE_USD] = true;\n allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS] = true;\n\n allowedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;\n allowedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;\n allowedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;\n\n allowedBaseKeys[Keys.MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT] = true;\n\n allowedBaseKeys[Keys.CREATE_DEPOSIT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CANCEL_DEPOSIT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_DEPOSIT_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CREATE_WITHDRAWAL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CANCEL_WITHDRAWAL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_WITHDRAWAL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CREATE_SHIFT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CANCEL_SHIFT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_SHIFT_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CREATE_ORDER_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_ORDER_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_ADL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.UPDATE_ORDER_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CANCEL_ORDER_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CREATE_GLV_DEPOSIT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CANCEL_GLV_DEPOSIT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CREATE_GLV_SHIFT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.EXECUTE_GLV_SHIFT_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.CLAIM_FUNDING_FEES_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CLAIM_COLLATERAL_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.CLAIM_UI_FEES_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.GENERAL_CLAIM_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.MIN_AFFILIATE_REWARD_FACTOR] = true;\n\n allowedBaseKeys[Keys.SUBACCOUNT_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.GASLESS_FEATURE_DISABLED] = true;\n\n allowedBaseKeys[Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS] = true;\n allowedBaseKeys[Keys.MAX_ORACLE_PRICE_AGE] = true;\n allowedBaseKeys[Keys.MAX_ATOMIC_ORACLE_PRICE_AGE] = true;\n allowedBaseKeys[Keys.MAX_ORACLE_TIMESTAMP_RANGE] = true;\n allowedBaseKeys[Keys.ORACLE_TIMESTAMP_ADJUSTMENT] = true;\n allowedBaseKeys[Keys.ORACLE_PROVIDER_MIN_CHANGE_DELAY] = true;\n allowedBaseKeys[Keys.CHAINLINK_PAYMENT_TOKEN] = true;\n allowedBaseKeys[Keys.SEQUENCER_GRACE_DURATION] = true;\n allowedBaseKeys[Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR] = true;\n\n allowedBaseKeys[Keys.POSITION_FEE_RECEIVER_FACTOR] = true;\n allowedBaseKeys[Keys.LIQUIDATION_FEE_RECEIVER_FACTOR] = true;\n allowedBaseKeys[Keys.SWAP_FEE_RECEIVER_FACTOR] = true;\n allowedBaseKeys[Keys.BORROWING_FEE_RECEIVER_FACTOR] = true;\n\n allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true;\n allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true;\n allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true;\n\n allowedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true;\n allowedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true;\n allowedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true;\n\n allowedBaseKeys[Keys.MAX_EXECUTION_FEE_MULTIPLIER_FACTOR] = true;\n\n allowedBaseKeys[Keys.CREATE_DEPOSIT_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.DEPOSIT_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.CREATE_WITHDRAWAL_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.WITHDRAWAL_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.CREATE_GLV_DEPOSIT_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.GLV_DEPOSIT_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.CREATE_GLV_WITHDRAWAL_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.GLV_WITHDRAWAL_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.GLV_SHIFT_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.GLV_PER_MARKET_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.SHIFT_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.SINGLE_SWAP_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.INCREASE_ORDER_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.DECREASE_ORDER_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.SWAP_ORDER_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.SET_TRADER_REFERRAL_CODE_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.TOKEN_TRANSFER_GAS_LIMIT] = true;\n allowedBaseKeys[Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT] = true;\n\n allowedBaseKeys[Keys.REQUEST_EXPIRATION_TIME] = true;\n allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR] = true;\n allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER] = true;\n allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION] = true;\n allowedBaseKeys[Keys.MIN_COLLATERAL_USD] = true;\n\n allowedBaseKeys[Keys.VIRTUAL_TOKEN_ID] = true;\n allowedBaseKeys[Keys.VIRTUAL_MARKET_ID] = true;\n allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_SWAPS] = true;\n allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_POSITIONS] = true;\n\n allowedBaseKeys[Keys.POSITION_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.POSITION_IMPACT_EXPONENT_FACTOR] = true;\n allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.POSITION_FEE_FACTOR] = true;\n allowedBaseKeys[Keys.PRO_DISCOUNT_FACTOR] = true;\n allowedBaseKeys[Keys.PRO_TRADER_TIER] = true;\n allowedBaseKeys[Keys.LIQUIDATION_FEE_FACTOR] = true;\n\n allowedBaseKeys[Keys.SWAP_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.SWAP_IMPACT_EXPONENT_FACTOR] = true;\n allowedBaseKeys[Keys.SWAP_FEE_FACTOR] = true;\n allowedBaseKeys[Keys.DEPOSIT_FEE_FACTOR] = true;\n allowedBaseKeys[Keys.WITHDRAWAL_FEE_FACTOR] = true;\n allowedBaseKeys[Keys.ATOMIC_SWAP_FEE_FACTOR] = true;\n allowedBaseKeys[Keys.ATOMIC_WITHDRAWAL_FEE_FACTOR] = true;\n\n allowedBaseKeys[Keys.MAX_UI_FEE_FACTOR] = true;\n allowedBaseKeys[Keys.MAX_AUTO_CANCEL_ORDERS] = true;\n allowedBaseKeys[Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS] = true;\n\n allowedBaseKeys[Keys.ORACLE_TYPE] = true;\n\n allowedBaseKeys[Keys.RESERVE_FACTOR] = true;\n allowedBaseKeys[Keys.OPEN_INTEREST_RESERVE_FACTOR] = true;\n\n allowedBaseKeys[Keys.MAX_PNL_FACTOR] = true;\n allowedBaseKeys[Keys.MIN_PNL_FACTOR_AFTER_ADL] = true;\n allowedBaseKeys[Keys.MAX_LENDABLE_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS] = true;\n allowedBaseKeys[Keys.MAX_LENDABLE_IMPACT_USD] = true;\n\n allowedBaseKeys[Keys.FUNDING_FACTOR] = true;\n allowedBaseKeys[Keys.FUNDING_EXPONENT_FACTOR] = true;\n allowedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.THRESHOLD_FOR_STABLE_FUNDING] = true;\n allowedBaseKeys[Keys.THRESHOLD_FOR_DECREASE_FUNDING] = true;\n\n allowedBaseKeys[Keys.OPTIMAL_USAGE_FACTOR] = true;\n allowedBaseKeys[Keys.BASE_BORROWING_FACTOR] = true;\n allowedBaseKeys[Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR] = true;\n allowedBaseKeys[Keys.BORROWING_FACTOR] = true;\n allowedBaseKeys[Keys.BORROWING_EXPONENT_FACTOR] = true;\n allowedBaseKeys[Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE] = true;\n\n allowedBaseKeys[Keys.PRICE_FEED_HEARTBEAT_DURATION] = true;\n\n allowedBaseKeys[Keys.IS_GLV_MARKET_DISABLED] = true;\n allowedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_USD] = true;\n allowedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT] = true;\n allowedBaseKeys[Keys.GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.GLV_SHIFT_MIN_INTERVAL] = true;\n allowedBaseKeys[Keys.MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT] = true;\n allowedBaseKeys[Keys.GLV_MAX_MARKET_COUNT] = true;\n\n allowedBaseKeys[Keys.SYNC_CONFIG_FEATURE_DISABLED] = true;\n allowedBaseKeys[Keys.SYNC_CONFIG_MARKET_DISABLED] = true;\n allowedBaseKeys[Keys.SYNC_CONFIG_PARAMETER_DISABLED] = true;\n allowedBaseKeys[Keys.SYNC_CONFIG_MARKET_PARAMETER_DISABLED] = true;\n\n allowedBaseKeys[Keys.BUYBACK_BATCH_AMOUNT] = true;\n allowedBaseKeys[Keys.BUYBACK_GMX_FACTOR] = true;\n allowedBaseKeys[Keys.BUYBACK_MAX_PRICE_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.BUYBACK_MAX_PRICE_AGE] = true;\n\n allowedBaseKeys[Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR] = true;\n\n allowedBaseKeys[Keys.IS_MULTICHAIN_PROVIDER_ENABLED] = true;\n allowedBaseKeys[Keys.IS_MULTICHAIN_ENDPOINT_ENABLED] = true;\n allowedBaseKeys[Keys.IS_RELAY_FEE_EXCLUDED] = true;\n allowedBaseKeys[Keys.IS_SRC_CHAIN_ID_ENABLED] = true;\n allowedBaseKeys[Keys.EID_TO_SRC_CHAIN_ID] = true;\n\n allowedBaseKeys[Keys.MAX_DATA_LENGTH] = true;\n\n allowedBaseKeys[Keys.CLAIMABLE_COLLATERAL_DELAY] = true;\n\n allowedBaseKeys[Keys.SUBACCOUNT_INTEGRATION_DISABLED] = true;\n allowedBaseKeys[Keys.RELAY_FEE_ADDRESS] = true;\n allowedBaseKeys[Keys.GELATO_RELAY_FEE_BASE_AMOUNT] = true;\n allowedBaseKeys[Keys.GELATO_RELAY_FEE_MULTIPLIER_FACTOR] = true;\n allowedBaseKeys[Keys.MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT] = true;\n\n allowedBaseKeys[Keys2.MULTICHAIN_READ_CHANNEL] = true;\n allowedBaseKeys[Keys2.MULTICHAIN_PEERS] = true;\n allowedBaseKeys[Keys2.MULTICHAIN_CONFIRMATIONS] = true;\n allowedBaseKeys[Keys2.MULTICHAIN_AUTHORIZED_ORIGINATORS] = true;\n\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_DAY] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_AMOUNT] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_FACTOR] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_ESGMX_AMOUNT] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_MAX_READ_RESPONSE_DELAY] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_GAS_LIMIT] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_CHAIN_ID] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_BRIDGE_SLIPPAGE_FACTOR] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_LAYERZERO_CHAIN_ID] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_ADDRESS_INFO] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_ADDRESS_INFO_FOR_CHAIN] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_CHAINLINK_FACTOR] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_MAX_WNT_AMOUNT_FROM_TREASURY] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_V1_FEES_WNT_FACTOR] = true;\n allowedBaseKeys[Keys2.FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR] = true;\n }\n\n function _initAllowedLimitedBaseKeys() internal {\n allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true;\n allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true;\n allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true;\n\n allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true;\n allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true;\n allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true;\n\n allowedLimitedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;\n allowedLimitedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;\n allowedLimitedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;\n allowedLimitedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;\n\n allowedLimitedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;\n allowedLimitedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;\n allowedLimitedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;\n\n allowedLimitedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_USD] = true;\n allowedLimitedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT] = true;\n\n allowedLimitedBaseKeys[Keys.PRO_TRADER_TIER] = true;\n }\n\n // @dev validate that the baseKey is allowed to be used\n // @param baseKey the base key to validate\n function _validateKey(bytes32 baseKey) internal view {\n if (roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)) {\n if (!allowedBaseKeys[baseKey]) {\n revert Errors.InvalidBaseKey(baseKey);\n }\n\n return;\n }\n\n if (roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER)) {\n if (!allowedLimitedBaseKeys[baseKey]) {\n revert Errors.InvalidBaseKey(baseKey);\n }\n\n return;\n }\n\n revert Errors.InvalidBaseKey(baseKey);\n }\n}\n" + }, + "contracts/config/ConfigSyncer.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./Config.sol\";\nimport \"./IRiskOracle.sol\";\nimport \"../feature/FeatureUtils.sol\";\n\n// @title ConfigSyncer\n// @dev Contract to handle market parameter updates\ncontract ConfigSyncer is ReentrancyGuard, RoleModule {\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.BoolItems;\n\n Config public immutable config;\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n address public immutable riskOracle;\n\n // @dev the base keys that can be set\n mapping(bytes32 => bool) public allowedBaseKeys;\n\n constructor(\n RoleStore _roleStore,\n Config _config,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n address _riskOracle\n ) RoleModule(_roleStore) {\n config = _config;\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n riskOracle = _riskOracle;\n\n _initAllowedBaseKeys();\n }\n\n // @dev Allows the LIMITED_CONFIG_KEEPER to apply updates with the provided markets and parameters\n // Values for parameters with the following base keys are not currently validated on-chain, they should be\n // validated off-chain if needed: MIN_FUNDING_FACTOR_PER_SECOND, MAX_POOL_AMOUNT, MAX_POOL_USD_FOR_DEPOSIT,\n // MAX_OPEN_INTEREST, POSITION_IMPACT_FACTOR, SWAP_IMPACT_FACTOR, RESERVE_FACTOR, OPEN_INTEREST_RESERVE_FACTOR\n // @param markets An array of market addresses for which updates are to be applied\n // @param parameters An array of parameters corresponding to each market for which updates are to be applied\n function sync(\n address[] calldata markets,\n string[] calldata parameters\n ) external onlyLimitedConfigKeeper nonReentrant {\n FeatureUtils.validateFeature(dataStore, Keys.syncConfigFeatureDisabledKey(address(this)));\n\n if (markets.length != parameters.length) {\n revert Errors.SyncConfigInvalidInputLengths(markets.length, parameters.length);\n }\n\n uint256 latestUpdateId = dataStore.getUint(Keys.syncConfigLatestUpdateIdKey());\n\n for (uint256 i; i < markets.length; i++) {\n address market = markets[i];\n string memory parameter = parameters[i];\n bool updateApplied;\n\n bool syncConfigMarketDisabled = dataStore.getBool(Keys.syncConfigMarketDisabledKey(market));\n if (syncConfigMarketDisabled) {\n revert Errors.SyncConfigUpdatesDisabledForMarket(market);\n }\n\n bool syncConfigParameterDisabled = dataStore.getBool(Keys.syncConfigParameterDisabledKey(parameter));\n if (syncConfigParameterDisabled) {\n revert Errors.SyncConfigUpdatesDisabledForParameter(parameter);\n }\n\n bool syncConfigMarketParameterDisabled = dataStore.getBool(\n Keys.syncConfigMarketParameterDisabledKey(market, parameter)\n );\n if (syncConfigMarketParameterDisabled) {\n revert Errors.SyncConfigUpdatesDisabledForMarketParameter(market, parameter);\n }\n\n IRiskOracle.RiskParameterUpdate memory riskParameterUpdate = IRiskOracle(riskOracle)\n .getLatestUpdateByParameterAndMarket(parameter, market);\n uint256 updateId = riskParameterUpdate.updateId;\n (bytes32 baseKey, bytes memory data) = abi.decode(riskParameterUpdate.additionalData, (bytes32, bytes));\n\n _validateMarketInData(baseKey, market, data);\n\n _validateKey(baseKey);\n\n bytes32 fullKey = Keys.getFullKey(baseKey, data);\n uint256 prevValue = dataStore.getUint(fullKey);\n uint256 updatedValue = Cast.bytesToUint256(riskParameterUpdate.newValue);\n\n bool syncConfigUpdateCompleted = dataStore.getBool(Keys.syncConfigUpdateCompletedKey(updateId));\n if (!syncConfigUpdateCompleted) {\n config.setUint(baseKey, data, updatedValue);\n dataStore.setBool(Keys.syncConfigUpdateCompletedKey(updateId), true);\n updateApplied = true;\n\n if (updateId > latestUpdateId) {\n latestUpdateId = updateId;\n }\n }\n\n EventUtils.EventLogData memory eventData;\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"updateId\", updateId);\n eventData.uintItems.setItem(1, \"prevValue\", prevValue);\n eventData.uintItems.setItem(2, \"nextValue\", updatedValue);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"updateApplied\", updateApplied);\n\n eventEmitter.emitEventLog(\"SyncConfig\", eventData);\n }\n\n if (latestUpdateId > dataStore.getUint(Keys.syncConfigLatestUpdateIdKey())) {\n dataStore.setUint(Keys.syncConfigLatestUpdateIdKey(), latestUpdateId);\n }\n }\n\n // @dev initialize the allowed base keys\n function _initAllowedBaseKeys() internal {\n allowedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;\n allowedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;\n allowedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;\n\n allowedBaseKeys[Keys.POSITION_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.POSITION_IMPACT_EXPONENT_FACTOR] = true;\n\n allowedBaseKeys[Keys.SWAP_IMPACT_FACTOR] = true;\n allowedBaseKeys[Keys.SWAP_IMPACT_EXPONENT_FACTOR] = true;\n\n allowedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;\n allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;\n\n allowedBaseKeys[Keys.OPTIMAL_USAGE_FACTOR] = true;\n allowedBaseKeys[Keys.BASE_BORROWING_FACTOR] = true;\n allowedBaseKeys[Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR] = true;\n allowedBaseKeys[Keys.BORROWING_FACTOR] = true;\n allowedBaseKeys[Keys.BORROWING_EXPONENT_FACTOR] = true;\n\n allowedBaseKeys[Keys.RESERVE_FACTOR] = true;\n allowedBaseKeys[Keys.OPEN_INTEREST_RESERVE_FACTOR] = true;\n }\n\n // @dev validate that the baseKey is allowed to be used\n // @param baseKey the base key to validate\n function _validateKey(bytes32 baseKey) internal view {\n if (!allowedBaseKeys[baseKey]) {\n revert Errors.InvalidBaseKey(baseKey);\n }\n }\n\n // @dev validate that the market within data is equal to market\n // With the exception of parameters that use the MAX_PNL_FACTOR base key, this function currently\n // only supports parameters for which the market address is the first element in the 'data' param\n // @param baseKey the base key to validate\n // @param market the market address\n // @param data the data used to compute fullKey\n function _validateMarketInData(bytes32 baseKey, address market, bytes memory data) internal pure {\n address marketFromData;\n if (baseKey == Keys.MAX_PNL_FACTOR) {\n (, /* bytes32 extKey */ marketFromData /* bool isLong */, ) = abi.decode(data, (bytes32, address, bool));\n } else {\n marketFromData = abi.decode(data, (address));\n }\n\n if (market != marketFromData) {\n revert Errors.SyncConfigInvalidMarketFromData(market, marketFromData);\n }\n }\n}\n" + }, + "contracts/config/ConfigTimelockController.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport {DataStore} from \"../data/DataStore.sol\";\nimport {Keys} from \"../data/Keys.sol\";\nimport {Errors} from \"../error/Errors.sol\";\nimport {EventEmitter} from \"../event/EventEmitter.sol\";\nimport {EventUtils} from \"../event/EventUtils.sol\";\nimport {Multicall3} from \"../mock/Multicall3.sol\";\nimport {OracleStore} from \"../oracle/OracleStore.sol\";\nimport {RoleStore} from \"../role/RoleStore.sol\";\nimport {Precision} from \"../utils/Precision.sol\";\nimport {TimelockController} from \"@openzeppelin/contracts/governance/TimelockController.sol\";\nimport {OracleModule} from \"../oracle/OracleModule.sol\";\nimport {OracleUtils} from \"../oracle/OracleUtils.sol\";\nimport {Oracle} from \"../oracle/Oracle.sol\";\nimport {PositionImpactPoolUtils} from \"../market/PositionImpactPoolUtils.sol\";\nimport {Chain} from \"../chain/Chain.sol\";\nimport {AccountUtils} from \"../utils/AccountUtils.sol\";\n\ncontract ConfigTimelockController is TimelockController, OracleModule {\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(\n uint256 minDelay,\n address[] memory proposers,\n address[] memory executors,\n Oracle oracle,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) TimelockController(minDelay, proposers, executors, msg.sender) OracleModule(oracle) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n modifier onlySelf() {\n if (msg.sender != address(this)) {\n revert Errors.Unauthorized(msg.sender, \"SELF\");\n }\n _;\n }\n\n // note that if on-chain prices are used for market operations, there may\n // be some difference in pricing between the on-chain price and e.g.\n // an off-chain data stream price\n // it should be ensured that the changes to the market token price that\n // result from this execution are not too large that it would lead to\n // significant arbitrage opportunities\n function executeWithOraclePrices(\n address target,\n uint256 value,\n bytes calldata payload,\n bytes32 predecessor,\n bytes32 salt,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external onlyRoleOrOpenRole(EXECUTOR_ROLE) withOraclePricesForAtomicAction(oracleParams) {\n execute(target, value, payload, predecessor, salt);\n }\n\n function withdrawFromPositionImpactPool(\n address market,\n address receiver,\n uint256 amount\n ) external onlySelf {\n PositionImpactPoolUtils.withdrawFromPositionImpactPool(\n dataStore,\n eventEmitter,\n oracle,\n market,\n receiver,\n amount\n );\n }\n\n function reduceLentImpactAmount(\n address market,\n address fundingAccount,\n uint256 reductionAmount\n ) external onlySelf {\n PositionImpactPoolUtils.reduceLentAmount(\n dataStore,\n eventEmitter,\n oracle,\n market,\n fundingAccount,\n reductionAmount\n );\n }\n}\n" + }, + "contracts/config/ConfigUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/Cast.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../market/MarketUtils.sol\";\n\nlibrary ConfigUtils {\n using SafeCast for int256;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BoolItems;\n\n struct InitOracleConfigPriceFeedParams {\n address feedAddress;\n uint256 multiplier;\n uint256 heartbeatDuration;\n uint256 stablePrice;\n }\n\n struct InitOracleConfigDataStreamParams {\n bytes32 feedId;\n uint256 multiplier;\n uint256 spreadReductionFactor;\n }\n\n struct InitOracleConfigEdgeParams {\n bytes32 feedId;\n uint256 tokenDecimals;\n }\n\n struct InitOracleConfigParams {\n address token;\n InitOracleConfigPriceFeedParams priceFeed;\n InitOracleConfigDataStreamParams dataStream;\n InitOracleConfigEdgeParams edge;\n }\n\n // 0.00001% per second, ~315% per year\n uint256 public constant MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND = 100000000000000000000000;\n // at this rate max allowed funding rate will be reached in 1 hour at 100% imbalance if max funding rate is 315%\n uint256 public constant MAX_ALLOWED_FUNDING_INCREASE_FACTOR_PER_SECOND = MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND / 1 hours;\n // at this rate zero funding rate will be reached in 24 hours if max funding rate is 315%\n uint256 public constant MAX_ALLOWED_FUNDING_DECREASE_FACTOR_PER_SECOND = MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND / 24 hours;\n // minimum duration required to fully distribute the position impact pool amount\n uint256 public constant MIN_POSITION_IMPACT_POOL_DISTRIBUTION_TIME = 7 days;\n\n // only allow initializing oracle config if there is no config set for any oracle provider\n // this is to prevent a malicious config keeper from misconfiguring an oracle provider for\n // a token then updating the token's oracle provider to the misconfigured provider\n // if updating of oracle config is needed for a token that already has an oracle config\n // the TimelockConfig should be used instead\n function initOracleConfig(\n DataStore dataStore,\n EventEmitter eventEmitter,\n InitOracleConfigParams memory params\n ) external {\n if (dataStore.getAddress(Keys.priceFeedKey(params.token)) != address(0)) {\n revert Errors.PriceFeedAlreadyExistsForToken(params.token);\n }\n\n if (dataStore.getBytes32(Keys.dataStreamIdKey(params.token)) != bytes32(0)) {\n revert Errors.DataStreamIdAlreadyExistsForToken(params.token);\n }\n\n if (dataStore.getBytes32(Keys.edgeDataStreamIdKey(params.token)) != bytes32(0)) {\n revert Errors.EdgeDataStreamIdAlreadyExistsForToken(params.token);\n }\n\n dataStore.setAddress(Keys.priceFeedKey(params.token), params.priceFeed.feedAddress);\n dataStore.setUint(Keys.priceFeedMultiplierKey(params.token), params.priceFeed.multiplier);\n dataStore.setUint(Keys.priceFeedHeartbeatDurationKey(params.token), params.priceFeed.heartbeatDuration);\n dataStore.setUint(Keys.stablePriceKey(params.token), params.priceFeed.stablePrice);\n\n validateRange(\n dataStore,\n Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR,\n abi.encode(params.token),\n params.dataStream.spreadReductionFactor\n );\n\n dataStore.setBytes32(Keys.dataStreamIdKey(params.token), params.dataStream.feedId);\n dataStore.setUint(Keys.dataStreamMultiplierKey(params.token), params.dataStream.multiplier);\n dataStore.setUint(Keys.dataStreamSpreadReductionFactorKey(params.token), params.dataStream.spreadReductionFactor);\n\n dataStore.setBytes32(Keys.edgeDataStreamIdKey(params.token), params.edge.feedId);\n dataStore.setUint(Keys.edgeDataStreamTokenDecimalsKey(params.token), params.edge.tokenDecimals);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"token\", params.token);\n eventData.addressItems.setItem(1, \"priceFeedAddress\", params.priceFeed.feedAddress);\n\n eventData.uintItems.initItems(6);\n eventData.uintItems.setItem(0, \"priceFeedMultiplier\", params.priceFeed.multiplier);\n eventData.uintItems.setItem(1, \"priceFeedHeartbeatDuration\", params.priceFeed.heartbeatDuration);\n eventData.uintItems.setItem(2, \"stablePrice\", params.priceFeed.stablePrice);\n eventData.uintItems.setItem(3, \"dataStreamMultiplier\", params.dataStream.multiplier);\n eventData.uintItems.setItem(4, \"dataStreamSpreadReductionFactor\", params.dataStream.spreadReductionFactor);\n eventData.uintItems.setItem(5, \"edgeDataStreamTokenDecimals\", params.edge.tokenDecimals);\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"dataStreamFeedId\", params.dataStream.feedId);\n eventData.bytes32Items.setItem(1, \"edgeDataStreamId\", params.edge.feedId);\n\n eventEmitter.emitEventLog1(\n \"InitOracleConfig\",\n Cast.toBytes32(params.token),\n eventData\n );\n }\n\n function setClaimableCollateralFactorForTime(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n uint256 factor\n ) external {\n if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); }\n\n bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey);\n dataStore.setUint(key, factor);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"timeKey\", timeKey);\n eventData.uintItems.setItem(1, \"factor\", factor);\n\n eventEmitter.emitEventLog2(\n \"SetClaimableCollateralFactorForTime\",\n Cast.toBytes32(market),\n Cast.toBytes32(token),\n eventData\n );\n }\n\n function setClaimableCollateralFactorForAccount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n address account,\n uint256 factor\n ) external {\n if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); }\n\n bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey, account);\n dataStore.setUint(key, factor);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"timeKey\", timeKey);\n eventData.uintItems.setItem(1, \"factor\", factor);\n\n eventEmitter.emitEventLog2(\n \"SetClaimableCollateralFactorForAccount\",\n Cast.toBytes32(market),\n Cast.toBytes32(token),\n eventData\n );\n }\n\n function setClaimableCollateralReductionFactorForAccount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n address account,\n uint256 factor\n ) external {\n if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableReductionFactor(factor); }\n\n bytes32 key = Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account);\n dataStore.setUint(key, factor);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"timeKey\", timeKey);\n eventData.uintItems.setItem(1, \"factor\", factor);\n\n eventEmitter.emitEventLog2(\n \"SetClaimableCollateralReductionFactorForAccount\",\n Cast.toBytes32(market),\n Cast.toBytes32(token),\n eventData\n );\n }\n\n function setPositionImpactDistributionRate(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n uint256 minPositionImpactPoolAmount,\n uint256 positionImpactPoolDistributionRate\n ) external {\n MarketUtils.distributePositionImpactPool(dataStore, eventEmitter, market);\n\n // Ensure the full positionImpactPoolAmount cannot be distributed in less then the minimum required time\n uint256 positionImpactPoolAmount = MarketUtils.getPositionImpactPoolAmount(dataStore, market);\n // positionImpactPoolDistributionRate has FLOAT_PRECISION, distributionAmount has WEI_PRECISION\n uint256 distributionAmount = Precision.applyFactor(MIN_POSITION_IMPACT_POOL_DISTRIBUTION_TIME, positionImpactPoolDistributionRate);\n if (positionImpactPoolAmount > 0) {\n if (distributionAmount >= positionImpactPoolAmount) {\n revert Errors.InvalidPositionImpactPoolDistributionRate(distributionAmount, positionImpactPoolAmount);\n }\n }\n\n dataStore.setUint(Keys.minPositionImpactPoolAmountKey(market), minPositionImpactPoolAmount);\n dataStore.setUint(Keys.positionImpactPoolDistributionRateKey(market), positionImpactPoolDistributionRate);\n\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"minPositionImpactPoolAmount\", minPositionImpactPoolAmount);\n eventData.uintItems.setItem(1, \"positionImpactPoolDistributionRate\", positionImpactPoolDistributionRate);\n\n eventEmitter.emitEventLog1(\n \"SetPositionImpactPoolDistributionRate\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n // @dev validate that the value is within the allowed range\n // @param baseKey the base key for the value\n // @param value the value to be set\n function validateRange(\n DataStore dataStore,\n bytes32 baseKey,\n bytes memory data,\n uint256 value\n ) public view {\n if (\n baseKey == Keys.SEQUENCER_GRACE_DURATION\n ) {\n if (value > 2 hours) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.CLAIMABLE_COLLATERAL_DELAY\n ) {\n if (value < 24 hours) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.MAX_FUNDING_FACTOR_PER_SECOND\n ) {\n if (value > MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n\n bytes32 minFundingFactorPerSecondKey = Keys.getFullKey(Keys.MIN_FUNDING_FACTOR_PER_SECOND, data);\n uint256 minFundingFactorPerSecond = dataStore.getUint(minFundingFactorPerSecondKey);\n if (value < minFundingFactorPerSecond) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.MIN_FUNDING_FACTOR_PER_SECOND\n ) {\n bytes32 maxFundingFactorPerSecondKey = Keys.getFullKey(Keys.MAX_FUNDING_FACTOR_PER_SECOND, data);\n uint256 maxFundingFactorPerSecond = dataStore.getUint(maxFundingFactorPerSecondKey);\n if (value > maxFundingFactorPerSecond) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.FUNDING_INCREASE_FACTOR_PER_SECOND\n ) {\n if (value > MAX_ALLOWED_FUNDING_INCREASE_FACTOR_PER_SECOND) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.FUNDING_DECREASE_FACTOR_PER_SECOND\n ) {\n if (value > MAX_ALLOWED_FUNDING_DECREASE_FACTOR_PER_SECOND) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.BORROWING_FACTOR ||\n baseKey == Keys.BASE_BORROWING_FACTOR\n ) {\n // 0.000005% per second, ~157% per year at 100% utilization\n if (value > 50000000000000000000000) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (baseKey == Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR) {\n // 0.00001% per second, ~315% per year at 100% utilization\n if (value > 100000000000000000000000) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.FUNDING_EXPONENT_FACTOR ||\n baseKey == Keys.BORROWING_EXPONENT_FACTOR\n ) {\n // revert if value > 2\n if (value > 2 * Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.POSITION_IMPACT_EXPONENT_FACTOR ||\n baseKey == Keys.SWAP_IMPACT_EXPONENT_FACTOR\n ) {\n // revert if value > 3\n if (value > 3 * Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.FUNDING_FACTOR ||\n baseKey == Keys.BORROWING_FACTOR ||\n baseKey == Keys.FUNDING_INCREASE_FACTOR_PER_SECOND ||\n baseKey == Keys.FUNDING_DECREASE_FACTOR_PER_SECOND ||\n baseKey == Keys.MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\n ) {\n // revert if value > 1%\n if (value > 1 * Precision.FLOAT_PRECISION / 100) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.SWAP_FEE_FACTOR ||\n baseKey == Keys.DEPOSIT_FEE_FACTOR ||\n baseKey == Keys.WITHDRAWAL_FEE_FACTOR ||\n baseKey == Keys.POSITION_FEE_FACTOR ||\n baseKey == Keys.MAX_UI_FEE_FACTOR ||\n baseKey == Keys.ATOMIC_SWAP_FEE_FACTOR ||\n baseKey == Keys.ATOMIC_WITHDRAWAL_FEE_FACTOR ||\n baseKey == Keys.BUYBACK_MAX_PRICE_IMPACT_FACTOR ||\n baseKey == Keys.MIN_COLLATERAL_FACTOR\n ) {\n // revert if value > 5%\n if (value > 5 * Precision.FLOAT_PRECISION / 100) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.MAX_LENDABLE_IMPACT_FACTOR ||\n baseKey == Keys.MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\n ) {\n // revert if value > 10%\n if (value > 10 * Precision.FLOAT_PRECISION / 100) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.MAX_LENDABLE_IMPACT_USD\n ) {\n // revert if value > 50,000\n if (value > 50 * 1000 * Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (baseKey == Keys.LIQUIDATION_FEE_FACTOR) {\n // revert if value > 1%\n if (value > Precision.FLOAT_PRECISION / 100) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (baseKey == Keys.MIN_COLLATERAL_USD) {\n // revert if value > 10 USD\n if (value > 10 * Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.POSITION_FEE_RECEIVER_FACTOR ||\n baseKey == Keys.SWAP_FEE_RECEIVER_FACTOR ||\n baseKey == Keys.BORROWING_FEE_RECEIVER_FACTOR ||\n baseKey == Keys.LIQUIDATION_FEE_RECEIVER_FACTOR ||\n baseKey == Keys.MAX_PNL_FACTOR ||\n baseKey == Keys.MIN_PNL_FACTOR_AFTER_ADL ||\n baseKey == Keys.OPTIMAL_USAGE_FACTOR ||\n baseKey == Keys.PRO_DISCOUNT_FACTOR ||\n baseKey == Keys.BUYBACK_GMX_FACTOR ||\n baseKey == Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR\n ) {\n // revert if value > 100%\n if (value > Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (baseKey == Keys.MAX_EXECUTION_FEE_MULTIPLIER_FACTOR) {\n if (value < Precision.FLOAT_PRECISION * 10 || value > Precision.FLOAT_PRECISION * 100_000) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n\n if (\n baseKey == Keys.RESERVE_FACTOR ||\n baseKey == Keys.OPEN_INTEREST_RESERVE_FACTOR\n ) {\n // revert if value > 10\n if (value > 10 * Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);\n }\n }\n }\n}\n" + }, + "contracts/config/IRiskOracle.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// Using interface for the Chaos Labs Risk Oracle contract so that importing the contract is not necessary\ninterface IRiskOracle {\n struct RiskParameterUpdate {\n uint256 timestamp;\n bytes newValue;\n string referenceId;\n bytes previousValue;\n string updateType;\n uint256 updateId;\n address market;\n bytes additionalData;\n }\n function getLatestUpdateByParameterAndMarket(string memory updateType, address market) external view returns (RiskParameterUpdate memory);\n}\n" + }, + "contracts/config/TimelockConfig.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport {Keys} from \"../data/Keys.sol\";\nimport {Errors} from \"../error/Errors.sol\";\nimport {EventEmitter} from \"../event/EventEmitter.sol\";\nimport {EventUtils} from \"../event/EventUtils.sol\";\nimport {RoleModule} from \"../role/RoleModule.sol\";\nimport {RoleStore} from \"../role/RoleStore.sol\";\nimport {DataStore} from \"../data/DataStore.sol\";\nimport {BasicMulticall} from \"../utils/BasicMulticall.sol\";\nimport {Precision} from \"../utils/Precision.sol\";\nimport {ConfigTimelockController} from \"./ConfigTimelockController.sol\";\nimport {OracleModule} from \"../oracle/OracleModule.sol\";\nimport {OracleUtils} from \"../oracle/OracleUtils.sol\";\nimport {MarketUtils} from \"../market/MarketUtils.sol\";\n\ncontract TimelockConfig is RoleModule, BasicMulticall {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n uint256 public constant MAX_TIMELOCK_DELAY = 5 days;\n\n EventEmitter public immutable eventEmitter;\n ConfigTimelockController public immutable timelockController;\n\n address public immutable dataStore;\n address public immutable oracleStore;\n\n constructor(\n EventEmitter _eventEmitter,\n address _dataStore,\n address _oracleStore,\n RoleStore _roleStore,\n ConfigTimelockController _timelockController\n ) RoleModule(_roleStore) {\n eventEmitter = _eventEmitter;\n dataStore = _dataStore;\n oracleStore = _oracleStore;\n timelockController = _timelockController;\n }\n\n // @dev signal granting of a role\n // @param account the account to grant the role\n // @param roleKey the role to grant\n function signalGrantRole(address account, bytes32 roleKey, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n bytes memory payload = abi.encodeWithSignature(\"grantRole(address,bytes32)\", account, roleKey);\n _schedule(address(roleStore), payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"roleKey\", roleKey);\n _signalPendingAction(\n \"SignalGrantRole\",\n eventData\n );\n }\n\n // @dev signal revoking of a role\n // @param account the account to revoke the role for\n // @param roleKey the role to revoke\n function signalRevokeRole(address account, bytes32 roleKey, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n\n bytes memory payload = abi.encodeWithSignature(\"revokeRole(address,bytes32)\",\n account, roleKey);\n _schedule(address(roleStore), payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"roleKey\", roleKey);\n _signalPendingAction(\n \"SignalRevokeRole\",\n eventData\n );\n }\n\n // @dev immediately revoke the role of an account\n // @param account the account to revoke the role for\n // @param roleKey the role to revoke\n function revokeRole(address account, bytes32 roleKey) external onlyTimelockMultisig {\n roleStore.revokeRole(account, roleKey);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"roleKey\", roleKey);\n _signalPendingAction(\n \"RevokeRole\",\n eventData\n );\n }\n\n function signalSetOracleProviderEnabled(address provider, bool value, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n bytes memory payload = abi.encodeWithSignature(\"setBool(bytes32,bool)\",\n Keys.isOracleProviderEnabledKey(provider), value);\n _schedule(dataStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"provider\", provider);\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"value\", value);\n _signalPendingAction(\n \"SignalSetOracleProviderEnabled\",\n eventData\n );\n }\n\n function signalSetOracleProviderForToken(address oracle, address token, address provider, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n bytes memory payload = abi.encodeWithSignature(\"setAddress(bytes32,address)\",\n Keys.oracleProviderForTokenKey(oracle, token), provider);\n _schedule(dataStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"oracle\", oracle);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"provider\", provider);\n _signalPendingAction(\n \"SignalSetOracleProviderForToken\",\n eventData\n );\n }\n\n function signalSetAtomicOracleProvider(address provider, bool value, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n bytes memory payload = abi.encodeWithSignature(\"setBool(bytes32,bool)\",\n Keys.isAtomicOracleProviderKey(provider), value);\n _schedule(dataStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"provider\", provider);\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"value\", value);\n _signalPendingAction(\n \"SignalSetAtomicOracleProvider\",\n eventData\n );\n }\n\n function signalAddOracleSigner(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n if (account == address(0)) {\n revert Errors.InvalidOracleSigner(account);\n }\n\n bytes memory payload = abi.encodeWithSignature(\"addSigner(address)\", account);\n _schedule(oracleStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n _signalPendingAction(\n \"SignalAddOracleSigner\",\n eventData\n );\n }\n\n function signalRemoveOracleSigner(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n if (account == address(0)) {\n revert Errors.InvalidOracleSigner(account);\n }\n\n bytes memory payload = abi.encodeWithSignature(\"removeSigner(address)\", account);\n _schedule(oracleStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n _signalPendingAction(\n \"SignalRemoveOracleSigner\",\n eventData\n );\n }\n\n // @dev signal setting of the fee receiver\n // @param account the new fee receiver\n function signalSetFeeReceiver(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n if (account == address(0)) {\n revert Errors.InvalidFeeReceiver(account);\n }\n\n bytes memory payload = abi.encodeWithSignature(\"setAddress(bytes32,address)\",\n Keys.FEE_RECEIVER, account);\n _schedule(dataStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n _signalPendingAction(\n \"SignalSetFeeReceiver\",\n eventData\n );\n }\n\n // @dev signal setting of the holding address\n // @param account of the new holding address\n function signalSetHoldingAddress(address account, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n if (account == address(0)) {\n revert Errors.InvalidHoldingAddress(account);\n }\n\n bytes memory payload = abi.encodeWithSignature(\"setAddress(bytes32,address)\",\n Keys.HOLDING_ADDRESS, account);\n _schedule(dataStore, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n _signalPendingAction(\n \"SignalSetHoldingAddress\",\n eventData\n );\n }\n\n // @dev signal setting of a price feed\n // @param token the token to set the price feed for\n // @param priceFeed the address of the price feed\n // @param priceFeedMultiplier the multiplier to apply to the price feed results\n // @param stablePrice the stable price to set a range for the price feed results\n function signalSetPriceFeed(\n address token,\n address priceFeed,\n uint256 priceFeedMultiplier,\n uint256 priceFeedHeartbeatDuration,\n uint256 stablePrice,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n\n bytes[] memory payloads = new bytes[](4);\n payloads[0] = abi.encodeWithSignature(\"setAddress(bytes32,address)\",\n Keys.priceFeedKey(token), priceFeed);\n payloads[1] = abi.encodeWithSignature(\"setUint(bytes32,uint256)\",\n Keys.priceFeedMultiplierKey(token), priceFeedMultiplier);\n payloads[2] = abi.encodeWithSignature(\"setUint(bytes32,uint256)\",\n Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration);\n payloads[3] = abi.encodeWithSignature(\"setUint(bytes32,uint256)\",\n Keys.stablePriceKey(token), stablePrice);\n\n _scheduleBatch(dataStore, payloads, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"token\", token);\n eventData.addressItems.setItem(1, \"priceFeed\", priceFeed);\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"priceFeedMultiplier\", priceFeedMultiplier);\n eventData.uintItems.setItem(1, \"priceFeedHeartbeatDuration\", priceFeedHeartbeatDuration);\n eventData.uintItems.setItem(2, \"stablePrice\", stablePrice);\n _signalPendingAction(\n \"SignalSetPriceFeed\",\n eventData\n );\n }\n\n // @dev signal setting of a data stream feed\n // @param token the token to set the data stream feed for\n // @param feedId the ID of the data stream feed\n // @param dataStreamMultiplier the multiplier to apply to the data stream feed results\n // @param dataStreamSpreadReductionFactor the factor to apply to the data stream price spread\n function signalSetDataStream(\n address token,\n bytes32 feedId,\n uint256 dataStreamMultiplier,\n uint256 dataStreamSpreadReductionFactor,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (dataStreamSpreadReductionFactor > Precision.FLOAT_PRECISION) {\n revert Errors.ConfigValueExceedsAllowedRange(Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR, dataStreamSpreadReductionFactor);\n }\n\n bytes[] memory payloads = new bytes[](3);\n payloads[0] = abi.encodeWithSignature(\"setBytes32(bytes32,bytes32)\",\n Keys.dataStreamIdKey(token), feedId);\n payloads[1] = abi.encodeWithSignature(\"setUint(bytes32,uint256)\",\n Keys.dataStreamMultiplierKey(token), dataStreamMultiplier);\n payloads[2] = abi.encodeWithSignature(\"setUint(bytes32,uint256)\",\n Keys.dataStreamSpreadReductionFactorKey(token), dataStreamSpreadReductionFactor);\n\n _scheduleBatch(dataStore, payloads, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"token\", token);\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"feedId\", feedId);\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"dataStreamMultiplier\", dataStreamMultiplier);\n eventData.uintItems.setItem(1, \"dataStreamSpreadReductionFactor\", dataStreamSpreadReductionFactor);\n _signalPendingAction(\n \"SignalSetDataStream\",\n eventData\n );\n }\n\n // @dev increase the timelock delay\n // @param the new timelock delay\n function increaseTimelockDelay(uint256 _timelockDelay, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n if (_timelockDelay <= timelockController.getMinDelay()) {\n revert Errors.InvalidTimelockDelay(_timelockDelay);\n }\n\n if (_timelockDelay > MAX_TIMELOCK_DELAY) {\n revert Errors.MaxTimelockDelayExceeded(_timelockDelay);\n }\n\n bytes memory payload = abi.encodeWithSignature(\"updateDelay(uint256)\", _timelockDelay);\n _schedule(address(timelockController), payload, predecessor, salt);\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"timelockDelay\", _timelockDelay);\n _signalPendingAction(\n \"IncreaseTimelockDelay\",\n eventData\n );\n }\n\n function signalReduceLentAmount(\n address market,\n address fundingAccount,\n uint256 reductionAmount,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (market == address(0)) {\n revert Errors.EmptyMarket();\n }\n if (fundingAccount == address(0)) {\n revert Errors.EmptyFundingAccount();\n }\n if (reductionAmount == 0) {\n revert Errors.EmptyReduceLentAmount();\n }\n\n bytes memory payload = abi.encodeWithSignature(\n \"reduceLentImpactAmount(address,address,uint256)\",\n market, fundingAccount, reductionAmount);\n _schedule(address(timelockController), payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"fundingAccount\", fundingAccount);\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"reductionAmount\", reductionAmount);\n _signalPendingAction(\n \"SignalReduceLentImpactAmount\",\n eventData\n );\n }\n\n // @dev Withdraw funds from position impact pool(negative price impacts) and send them to `receiver`\n // @param market Market from withdraw\n // @param receiver Account to send funds from pool\n // @param amount Amount of tokens to withdraw\n function signalWithdrawFromPositionImpactPool(\n address market,\n address receiver,\n uint256 amount,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (market == address(0)) {\n revert Errors.EmptyMarket();\n }\n if (receiver == address(0)) {\n revert Errors.EmptyReceiver();\n }\n if (amount == 0) {\n revert Errors.EmptyPositionImpactWithdrawalAmount();\n }\n\n bytes memory payload = abi.encodeWithSignature(\n \"withdrawFromPositionImpactPool(address,address,uint256)\",\n market, receiver, amount);\n _schedule(address(timelockController), payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"receiver\", receiver);\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n _signalPendingAction(\n \"SignalWithdrawFromPositionImpactPool\",\n eventData\n );\n }\n\n function signalWithdrawTokens(\n address target,\n address token,\n address receiver,\n uint256 amount,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (target == address(0)) {\n revert Errors.EmptyTarget();\n }\n if (token == address(0)) {\n revert Errors.EmptyToken();\n }\n if (receiver == address(0)) {\n revert Errors.EmptyReceiver();\n }\n if (amount == 0) {\n revert Errors.EmptyWithdrawalAmount();\n }\n\n bytes memory payload = abi.encodeWithSignature(\n \"withdrawTokens(address,address,uint256)\",\n token,\n receiver,\n amount\n );\n _schedule(target, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"target\", target);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"receiver\", receiver);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n\n _signalPendingAction(\"SignalWithdrawTokens\", eventData);\n }\n\n function signalSetEdgeDataStream(\n address token,\n bytes32 edgeDataStreamId,\n uint256 edgeDataStreamTokenDecimals,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (edgeDataStreamId == bytes32(0)) {\n revert Errors.EmptyDataStreamFeedId(token);\n }\n\n bytes[] memory payloads = new bytes[](2);\n payloads[0] = abi.encodeWithSignature(\"setBytes32(bytes32,bytes32)\",\n Keys.edgeDataStreamIdKey(token), edgeDataStreamId);\n payloads[1] = abi.encodeWithSignature(\"setUint(bytes32,uint256)\",\n Keys.edgeDataStreamTokenDecimalsKey(token), edgeDataStreamTokenDecimals);\n\n _scheduleBatch(dataStore, payloads, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"token\", token);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"edgeDataStreamId\", edgeDataStreamId);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"edgeDataStreamTokenDecimals\", edgeDataStreamTokenDecimals);\n\n _signalPendingAction(\"SignalSetEdgeDataStream\", eventData);\n }\n\n function signalSetMinContributorPaymentInterval(\n address target,\n uint256 interval,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (target == address(0)) {\n revert Errors.EmptyTarget();\n }\n if (interval < 20 days) {\n revert Errors.MinContributorPaymentIntervalBelowAllowedRange(interval);\n }\n\n bytes memory payload = abi.encodeWithSignature(\n \"setMinContributorPaymentInterval(uint256)\",\n interval\n );\n _schedule(target, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"interval\", interval);\n\n _signalPendingAction(\"SignalSetMinContributorPaymentInterval\", eventData);\n }\n\n function signalSetMaxTotalContributorTokenAmount(\n address target,\n address[] calldata tokens,\n uint256[] calldata amounts,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n if (target == address(0)) {\n revert Errors.EmptyTarget();\n }\n if (tokens.length != amounts.length) {\n revert Errors.InvalidSetMaxTotalContributorTokenAmountInput(tokens.length, amounts.length);\n }\n for (uint256 i; i < tokens.length; i++) {\n address token = tokens[i];\n if (!DataStore(dataStore).containsAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token)) {\n revert Errors.InvalidContributorToken(token);\n }\n }\n\n bytes memory payload = abi.encodeWithSignature(\n \"setMaxTotalContributorTokenAmount(address[],uint256[])\",\n tokens,\n amounts\n );\n _schedule(target, payload, predecessor, salt);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initArrayItems(1);\n eventData.addressItems.setItem(0, \"tokens\", tokens);\n\n eventData.uintItems.initArrayItems(1);\n eventData.uintItems.setItem(0, \"amounts\", amounts);\n\n _signalPendingAction(\"SignalSetMaxTotalContributorTokenAmount\", eventData);\n }\n\n function execute(address target, bytes calldata payload, bytes32 predecessor, bytes32 salt) external onlyTimelockAdmin {\n timelockController.execute(target, 0, payload, predecessor, salt);\n }\n\n function executeWithOraclePrice(\n address target,\n bytes calldata payload,\n bytes32 predecessor,\n bytes32 salt,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external onlyTimelockAdmin {\n timelockController.executeWithOraclePrices(\n target, 0, payload, predecessor, salt, oracleParams\n );\n }\n\n function executeBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata payloads,\n bytes32 predecessor,\n bytes32 salt\n ) external onlyTimelockAdmin {\n timelockController.executeBatch(targets, values, payloads, predecessor, salt);\n }\n\n function getHash(address target, bytes calldata payload, bytes32 predecessor, bytes32 salt) external view returns (bytes32) {\n return timelockController.hashOperation(target, 0, payload, predecessor, salt);\n }\n\n function getHashBatch(\n address[] calldata targets,\n bytes[] calldata payloads,\n uint256[] calldata values,\n bytes32 predecessor,\n bytes32 salt\n ) external view returns (bytes32) {\n return timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt);\n }\n\n function cancelAction(bytes32 id) external onlyTimelockAdmin {\n timelockController.cancel(id);\n }\n\n function _schedule(\n address target,\n bytes memory payload,\n bytes32 predecessor,\n bytes32 salt\n ) internal {\n timelockController.schedule(target, 0, payload, predecessor, salt, timelockController.getMinDelay());\n }\n\n function _scheduleBatch(\n address target,\n bytes[] memory payloads,\n bytes32 predecessor,\n bytes32 salt\n ) internal {\n uint256 payloadCount = payloads.length;\n address[] memory targets = new address[](payloadCount);\n for (uint256 i; i < payloadCount; i++) {\n targets[i] = target;\n }\n uint256[] memory values = new uint256[](payloadCount);\n timelockController.scheduleBatch(\n targets,\n values,\n payloads,\n predecessor,\n salt,\n timelockController.getMinDelay()\n );\n }\n\n function _signalPendingAction(string memory actionLabel, EventUtils.EventLogData memory eventData) internal {\n EventUtils.EventLogData memory actionData;\n\n bytes32 actionKey = keccak256(abi.encode(actionLabel));\n\n actionData.bytes32Items.initItems(1);\n actionData.bytes32Items.setItem(0, \"actionKey\", actionKey);\n\n actionData.stringItems.initItems(1);\n actionData.stringItems.setItem(0, \"actionLabel\", actionLabel);\n\n eventEmitter.emitEventLog1(\n \"SignalPendingAction\",\n actionKey,\n actionData\n );\n\n eventEmitter.emitEventLog(\n actionLabel,\n eventData\n );\n }\n}\n" + }, + "contracts/contributor/ContributorHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../role/RoleModule.sol\";\n\nimport \"../chain/Chain.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/BasicMulticall.sol\";\nimport \"../utils/Cast.sol\";\n\n// @title ContributorHandler\ncontract ContributorHandler is ReentrancyGuard, RoleModule, BasicMulticall {\n using SafeERC20 for IERC20;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n // note that since there will be account * token number of iterations in some functions\n // and that the CONTRIBUTOR_ACCOUNT_LIST and CONTRIBUTOR_TOKEN_LIST will be loaded entirely\n // into memory\n // care should be taken to not have too many accounts / tokens such that the block gas limit\n // or other execution limits is exceeded\n function addContributorAccount(address account) external nonReentrant onlyContributorKeeper {\n dataStore.addAddress(Keys.CONTRIBUTOR_ACCOUNT_LIST, account);\n }\n\n function removeContributorAccount(address account) external nonReentrant onlyContributorKeeper {\n dataStore.removeAddress(Keys.CONTRIBUTOR_ACCOUNT_LIST, account);\n }\n\n function addContributorToken(address token) external nonReentrant onlyContributorKeeper {\n dataStore.addAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token);\n }\n\n function removeContributorToken(address token) external nonReentrant onlyContributorKeeper {\n dataStore.removeAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token);\n }\n\n function setContributorFundingAccount(address token, address fundingAccount) external nonReentrant onlyContributorKeeper {\n dataStore.setAddress(Keys.contributorFundingAccountKey(token), fundingAccount);\n }\n\n function setCustomContributorFundingAccount(address account, address token, address fundingAccount) external nonReentrant onlyContributorKeeper {\n dataStore.setAddress(Keys.customContributorFundingAccountKey(account, token), fundingAccount);\n }\n\n function setMinContributorPaymentInterval(uint256 interval) external nonReentrant onlyController {\n // revert if < 20 days\n if (interval < 20 days) {\n revert Errors.MinContributorPaymentIntervalBelowAllowedRange(interval);\n }\n\n dataStore.setUint(Keys.MIN_CONTRIBUTOR_PAYMENT_INTERVAL, interval);\n }\n\n function setMaxTotalContributorTokenAmount(\n address[] memory tokens,\n uint256[] memory amounts\n ) external nonReentrant onlyController {\n if (tokens.length != amounts.length) {\n revert Errors.InvalidSetMaxTotalContributorTokenAmountInput(tokens.length, amounts.length);\n }\n\n for (uint256 i; i < tokens.length; i++) {\n address token = tokens[i];\n if (!dataStore.containsAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token)) {\n revert Errors.InvalidContributorToken(token);\n }\n dataStore.setUint(Keys.maxTotalContributorTokenAmountKey(token), amounts[i]);\n }\n\n _validateMaxContributorTokenAmounts();\n }\n\n function sendPayments() external nonReentrant onlyContributorDistributor {\n uint256 lastPaymentAt = dataStore.getUint(Keys.CONTRIBUTOR_LAST_PAYMENT_AT);\n uint256 minPaymentInterval = dataStore.getUint(Keys.MIN_CONTRIBUTOR_PAYMENT_INTERVAL);\n\n if (lastPaymentAt + minPaymentInterval > Chain.currentTimestamp()) {\n revert Errors.MinContributorPaymentIntervalNotYetPassed(minPaymentInterval);\n }\n\n uint256 tokenCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_TOKEN_LIST);\n uint256 accountCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_ACCOUNT_LIST);\n\n address[] memory tokens = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_TOKEN_LIST, 0, tokenCount);\n address[] memory accounts = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_ACCOUNT_LIST, 0, accountCount);\n\n for (uint256 i; i < tokenCount; i++) {\n address token = tokens[i];\n address mainFundingAccount = dataStore.getAddress(Keys.contributorFundingAccountKey(token));\n\n for (uint256 j; j < accountCount; j++) {\n address account = accounts[j];\n address fundingAccount = dataStore.getAddress(Keys.customContributorFundingAccountKey(account, token));\n if (fundingAccount == address(0)) {\n fundingAccount = mainFundingAccount;\n }\n\n uint256 amount = dataStore.getUint(Keys.contributorTokenAmountKey(account, token));\n\n IERC20(token).safeTransferFrom(fundingAccount, account, amount);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"fundingAccount\", fundingAccount);\n eventData.addressItems.setItem(1, \"account\", account);\n eventData.addressItems.setItem(2, \"token\", token);\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventEmitter.emitEventLog1(\n \"SendContributorPayment\",\n Cast.toBytes32(account),\n eventData\n );\n }\n }\n\n dataStore.setUint(Keys.CONTRIBUTOR_LAST_PAYMENT_AT, Chain.currentTimestamp());\n }\n\n function setContributorAmount(\n address account,\n address[] memory tokens,\n uint256[] memory amounts\n ) external nonReentrant onlyContributorKeeper {\n if (tokens.length != amounts.length) {\n revert Errors.InvalidSetContributorPaymentInput(tokens.length, amounts.length);\n }\n\n for (uint256 i; i < tokens.length; i++) {\n address token = tokens[i];\n if (!dataStore.containsAddress(Keys.CONTRIBUTOR_TOKEN_LIST, token)) {\n revert Errors.InvalidContributorToken(token);\n }\n\n uint256 amount = amounts[i];\n dataStore.setUint(Keys.contributorTokenAmountKey(account, token), amount);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventEmitter.emitEventLog1(\n \"SetContributorAmount\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n _validateMaxContributorTokenAmounts();\n }\n\n // note that this is just a sanity validation since the maxTotalContributorTokenAmount\n // can technically be exceeded since can be separately updated in Config\n function _validateMaxContributorTokenAmounts() internal view {\n uint256 tokenCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_TOKEN_LIST);\n uint256 accountCount = dataStore.getAddressCount(Keys.CONTRIBUTOR_ACCOUNT_LIST);\n\n address[] memory tokens = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_TOKEN_LIST, 0, tokenCount);\n address[] memory accounts = dataStore.getAddressValuesAt(Keys.CONTRIBUTOR_ACCOUNT_LIST, 0, accountCount);\n\n for (uint256 i; i < tokenCount; i++) {\n address token = tokens[i];\n uint256 totalAmount;\n\n for (uint256 j; j < accountCount; j++) {\n address account = accounts[j];\n uint256 amount = dataStore.getUint(Keys.contributorTokenAmountKey(account, token));\n totalAmount += amount;\n }\n\n uint256 maxTotalAmount = dataStore.getUint(Keys.maxTotalContributorTokenAmountKey(token));\n if (totalAmount > maxTotalAmount) {\n revert Errors.MaxTotalContributorTokenAmountExceeded(token, totalAmount, maxTotalAmount);\n }\n }\n }\n}\n" + }, + "contracts/data/DataStore.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../role/RoleModule.sol\";\nimport \"../utils/Calc.sol\";\n\n// @title DataStore\n// @dev DataStore for all general state values\ncontract DataStore is RoleModule {\n using SafeCast for int256;\n\n using EnumerableSet for EnumerableSet.Bytes32Set;\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableSet for EnumerableSet.UintSet;\n using EnumerableValues for EnumerableSet.Bytes32Set;\n using EnumerableValues for EnumerableSet.AddressSet;\n using EnumerableValues for EnumerableSet.UintSet;\n\n // store for uint values\n mapping(bytes32 => uint256) public uintValues;\n // store for int values\n mapping(bytes32 => int256) public intValues;\n // store for address values\n mapping(bytes32 => address) public addressValues;\n // store for bool values\n mapping(bytes32 => bool) public boolValues;\n // store for string values\n mapping(bytes32 => string) public stringValues;\n // store for bytes32 values\n mapping(bytes32 => bytes32) public bytes32Values;\n\n // store for uint[] values\n mapping(bytes32 => uint256[]) public uintArrayValues;\n // store for int[] values\n mapping(bytes32 => int256[]) public intArrayValues;\n // store for address[] values\n mapping(bytes32 => address[]) public addressArrayValues;\n // store for bool[] values\n mapping(bytes32 => bool[]) public boolArrayValues;\n // store for string[] values\n mapping(bytes32 => string[]) public stringArrayValues;\n // store for bytes32[] values\n mapping(bytes32 => bytes32[]) public bytes32ArrayValues;\n\n // store for bytes32 sets\n mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;\n // store for address sets\n mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;\n // store for uint256 sets\n mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;\n\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n // @dev get the uint value for the given key\n // @param key the key of the value\n // @return the uint value for the key\n function getUint(bytes32 key) external view returns (uint256) {\n return uintValues[key];\n }\n\n // @dev set the uint value for the given key\n // @param key the key of the value\n // @param value the value to set\n // @return the uint value for the key\n function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\n uintValues[key] = value;\n return value;\n }\n\n // @dev delete the uint value for the given key\n // @param key the key of the value\n function removeUint(bytes32 key) external onlyController {\n delete uintValues[key];\n }\n\n // @dev add the input int value to the existing uint value\n // @param key the key of the value\n // @param value the input int value\n // @return the new uint value\n function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {\n uint256 currValue = uintValues[key];\n if (value < 0 && (-value).toUint256() > currValue) {\n revert(errorMessage);\n }\n uint256 nextUint = Calc.sumReturnUint256(currValue, value);\n uintValues[key] = nextUint;\n return nextUint;\n }\n\n // @dev add the input uint value to the existing uint value\n // @param key the key of the value\n // @param value the input int value\n // @return the new uint value\n function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\n uint256 currValue = uintValues[key];\n uint256 nextUint = currValue + value;\n uintValues[key] = nextUint;\n return nextUint;\n }\n\n // @dev add the input int value to the existing uint value, prevent the uint\n // value from becoming negative\n // @param key the key of the value\n // @param value the input int value\n // @return the new uint value\n function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {\n uint256 uintValue = uintValues[key];\n if (value < 0 && (-value).toUint256() > uintValue) {\n uintValues[key] = 0;\n return 0;\n }\n\n uint256 nextUint = Calc.sumReturnUint256(uintValue, value);\n uintValues[key] = nextUint;\n return nextUint;\n }\n\n // @dev add the input uint value to the existing uint value\n // @param key the key of the value\n // @param value the input uint value\n // @return the new uint value\n function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\n uint256 nextUint = uintValues[key] + value;\n uintValues[key] = nextUint;\n return nextUint;\n }\n\n // @dev subtract the input uint value from the existing uint value\n // @param key the key of the value\n // @param value the input uint value\n // @return the new uint value\n function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {\n uint256 nextUint = uintValues[key] - value;\n uintValues[key] = nextUint;\n return nextUint;\n }\n\n // @dev get the int value for the given key\n // @param key the key of the value\n // @return the int value for the key\n function getInt(bytes32 key) external view returns (int256) {\n return intValues[key];\n }\n\n // @dev set the int value for the given key\n // @param key the key of the value\n // @param value the value to set\n // @return the int value for the key\n function setInt(bytes32 key, int256 value) external onlyController returns (int256) {\n intValues[key] = value;\n return value;\n }\n\n function removeInt(bytes32 key) external onlyController {\n delete intValues[key];\n }\n\n // @dev add the input int value to the existing int value\n // @param key the key of the value\n // @param value the input int value\n // @return the new int value\n function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {\n int256 nextInt = intValues[key] + value;\n intValues[key] = nextInt;\n return nextInt;\n }\n\n // @dev add the input int value to the existing int value\n // @param key the key of the value\n // @param value the input int value\n // @return the new int value\n function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\n int256 nextInt = intValues[key] + value;\n intValues[key] = nextInt;\n return nextInt;\n }\n\n // @dev subtract the input int value from the existing int value\n // @param key the key of the value\n // @param value the input int value\n // @return the new int value\n function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {\n int256 nextInt = intValues[key] - value;\n intValues[key] = nextInt;\n return nextInt;\n }\n\n // @dev get the address value for the given key\n // @param key the key of the value\n // @return the address value for the key\n function getAddress(bytes32 key) external view returns (address) {\n return addressValues[key];\n }\n\n // @dev set the address value for the given key\n // @param key the key of the value\n // @param value the value to set\n // @return the address value for the key\n function setAddress(bytes32 key, address value) external onlyController returns (address) {\n addressValues[key] = value;\n return value;\n }\n\n // @dev delete the address value for the given key\n // @param key the key of the value\n function removeAddress(bytes32 key) external onlyController {\n delete addressValues[key];\n }\n\n // @dev get the bool value for the given key\n // @param key the key of the value\n // @return the bool value for the key\n function getBool(bytes32 key) external view returns (bool) {\n return boolValues[key];\n }\n\n // @dev set the bool value for the given key\n // @param key the key of the value\n // @param value the value to set\n // @return the bool value for the key\n function setBool(bytes32 key, bool value) external onlyController returns (bool) {\n boolValues[key] = value;\n return value;\n }\n\n // @dev delete the bool value for the given key\n // @param key the key of the value\n function removeBool(bytes32 key) external onlyController {\n delete boolValues[key];\n }\n\n // @dev get the string value for the given key\n // @param key the key of the value\n // @return the string value for the key\n function getString(bytes32 key) external view returns (string memory) {\n return stringValues[key];\n }\n\n // @dev set the string value for the given key\n // @param key the key of the value\n // @param value the value to set\n // @return the string value for the key\n function setString(bytes32 key, string memory value) external onlyController returns (string memory) {\n stringValues[key] = value;\n return value;\n }\n\n // @dev delete the string value for the given key\n // @param key the key of the value\n function removeString(bytes32 key) external onlyController {\n delete stringValues[key];\n }\n\n // @dev get the bytes32 value for the given key\n // @param key the key of the value\n // @return the bytes32 value for the key\n function getBytes32(bytes32 key) external view returns (bytes32) {\n return bytes32Values[key];\n }\n\n // @dev set the bytes32 value for the given key\n // @param key the key of the value\n // @param value the value to set\n // @return the bytes32 value for the key\n function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {\n bytes32Values[key] = value;\n return value;\n }\n\n // @dev delete the bytes32 value for the given key\n // @param key the key of the value\n function removeBytes32(bytes32 key) external onlyController {\n delete bytes32Values[key];\n }\n\n // @dev get the uint array for the given key\n // @param key the key of the uint array\n // @return the uint array for the key\n function getUintArray(bytes32 key) external view returns (uint256[] memory) {\n return uintArrayValues[key];\n }\n\n // @dev set the uint array for the given key\n // @param key the key of the uint array\n // @param value the value of the uint array\n function setUintArray(bytes32 key, uint256[] memory value) external onlyController {\n uintArrayValues[key] = value;\n }\n\n // @dev delete the uint array for the given key\n // @param key the key of the uint array\n // @param value the value of the uint array\n function removeUintArray(bytes32 key) external onlyController {\n delete uintArrayValues[key];\n }\n\n // @dev get the int array for the given key\n // @param key the key of the int array\n // @return the int array for the key\n function getIntArray(bytes32 key) external view returns (int256[] memory) {\n return intArrayValues[key];\n }\n\n // @dev set the int array for the given key\n // @param key the key of the int array\n // @param value the value of the int array\n function setIntArray(bytes32 key, int256[] memory value) external onlyController {\n intArrayValues[key] = value;\n }\n\n // @dev delete the int array for the given key\n // @param key the key of the int array\n // @param value the value of the int array\n function removeIntArray(bytes32 key) external onlyController {\n delete intArrayValues[key];\n }\n\n // @dev get the address array for the given key\n // @param key the key of the address array\n // @return the address array for the key\n function getAddressArray(bytes32 key) external view returns (address[] memory) {\n return addressArrayValues[key];\n }\n\n // @dev set the address array for the given key\n // @param key the key of the address array\n // @param value the value of the address array\n function setAddressArray(bytes32 key, address[] memory value) external onlyController {\n addressArrayValues[key] = value;\n }\n\n // @dev delete the address array for the given key\n // @param key the key of the address array\n // @param value the value of the address array\n function removeAddressArray(bytes32 key) external onlyController {\n delete addressArrayValues[key];\n }\n\n // @dev get the bool array for the given key\n // @param key the key of the bool array\n // @return the bool array for the key\n function getBoolArray(bytes32 key) external view returns (bool[] memory) {\n return boolArrayValues[key];\n }\n\n // @dev set the bool array for the given key\n // @param key the key of the bool array\n // @param value the value of the bool array\n function setBoolArray(bytes32 key, bool[] memory value) external onlyController {\n boolArrayValues[key] = value;\n }\n\n // @dev delete the bool array for the given key\n // @param key the key of the bool array\n // @param value the value of the bool array\n function removeBoolArray(bytes32 key) external onlyController {\n delete boolArrayValues[key];\n }\n\n // @dev get the string array for the given key\n // @param key the key of the string array\n // @return the string array for the key\n function getStringArray(bytes32 key) external view returns (string[] memory) {\n return stringArrayValues[key];\n }\n\n // @dev set the string array for the given key\n // @param key the key of the string array\n // @param value the value of the string array\n function setStringArray(bytes32 key, string[] memory value) external onlyController {\n stringArrayValues[key] = value;\n }\n\n // @dev delete the string array for the given key\n // @param key the key of the string array\n // @param value the value of the string array\n function removeStringArray(bytes32 key) external onlyController {\n delete stringArrayValues[key];\n }\n\n // @dev get the bytes32 array for the given key\n // @param key the key of the bytes32 array\n // @return the bytes32 array for the key\n function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {\n return bytes32ArrayValues[key];\n }\n\n // @dev set the bytes32 array for the given key\n // @param key the key of the bytes32 array\n // @param value the value of the bytes32 array\n function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {\n bytes32ArrayValues[key] = value;\n }\n\n // @dev delete the bytes32 array for the given key\n // @param key the key of the bytes32 array\n // @param value the value of the bytes32 array\n function removeBytes32Array(bytes32 key) external onlyController {\n delete bytes32ArrayValues[key];\n }\n\n // @dev check whether the given value exists in the set\n // @param setKey the key of the set\n // @param value the value to check\n function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {\n return bytes32Sets[setKey].contains(value);\n }\n\n // @dev get the length of the set\n // @param setKey the key of the set\n function getBytes32Count(bytes32 setKey) external view returns (uint256) {\n return bytes32Sets[setKey].length();\n }\n\n // @dev get the values of the set in the given range\n // @param setKey the key of the set\n // @param the start of the range, values at the start index will be returned\n // in the result\n // @param the end of the range, values at the end index will not be returned\n // in the result\n function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {\n return bytes32Sets[setKey].valuesAt(start, end);\n }\n\n // @dev add the given value to the set\n // @param setKey the key of the set\n // @param value the value to add\n function addBytes32(bytes32 setKey, bytes32 value) external onlyController {\n bytes32Sets[setKey].add(value);\n }\n\n // @dev remove the given value from the set\n // @param setKey the key of the set\n // @param value the value to remove\n function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {\n bytes32Sets[setKey].remove(value);\n }\n\n // @dev check whether the given value exists in the set\n // @param setKey the key of the set\n // @param value the value to check\n function containsAddress(bytes32 setKey, address value) external view returns (bool) {\n return addressSets[setKey].contains(value);\n }\n\n // @dev get the length of the set\n // @param setKey the key of the set\n function getAddressCount(bytes32 setKey) external view returns (uint256) {\n return addressSets[setKey].length();\n }\n\n // @dev get the values of the set in the given range\n // @param setKey the key of the set\n // @param the start of the range, values at the start index will be returned\n // in the result\n // @param the end of the range, values at the end index will not be returned\n // in the result\n function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {\n return addressSets[setKey].valuesAt(start, end);\n }\n\n // @dev add the given value to the set\n // @param setKey the key of the set\n // @param value the value to add\n function addAddress(bytes32 setKey, address value) external onlyController {\n addressSets[setKey].add(value);\n }\n\n // @dev remove the given value from the set\n // @param setKey the key of the set\n // @param value the value to remove\n function removeAddress(bytes32 setKey, address value) external onlyController {\n addressSets[setKey].remove(value);\n }\n\n // @dev check whether the given value exists in the set\n // @param setKey the key of the set\n // @param value the value to check\n function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {\n return uintSets[setKey].contains(value);\n }\n\n // @dev get the length of the set\n // @param setKey the key of the set\n function getUintCount(bytes32 setKey) external view returns (uint256) {\n return uintSets[setKey].length();\n }\n\n // @dev get the values of the set in the given range\n // @param setKey the key of the set\n // @param the start of the range, values at the start index will be returned\n // in the result\n // @param the end of the range, values at the end index will not be returned\n // in the result\n function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {\n return uintSets[setKey].valuesAt(start, end);\n }\n\n // @dev add the given value to the set\n // @param setKey the key of the set\n // @param value the value to add\n function addUint(bytes32 setKey, uint256 value) external onlyController {\n uintSets[setKey].add(value);\n }\n\n // @dev remove the given value from the set\n // @param setKey the key of the set\n // @param value the value to remove\n function removeUint(bytes32 setKey, uint256 value) external onlyController {\n uintSets[setKey].remove(value);\n }\n}\n" + }, + "contracts/data/Keys.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title Keys\n// @dev Keys for values in the DataStore\nlibrary Keys {\n // @dev key for the address of the wrapped native token\n bytes32 public constant WNT = keccak256(abi.encode(\"WNT\"));\n // @dev key for the nonce value used in NonceUtils\n bytes32 public constant NONCE = keccak256(abi.encode(\"NONCE\"));\n\n // @dev for sending received fees\n bytes32 public constant FEE_RECEIVER = keccak256(abi.encode(\"FEE_RECEIVER\"));\n\n // @dev for holding tokens that could not be sent out\n bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode(\"HOLDING_ADDRESS\"));\n bytes32 public constant RELAY_FEE_ADDRESS = keccak256(abi.encode(\"RELAY_FEE_ADDRESS\"));\n\n // @dev key for the minimum gas for execution error\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode(\"MIN_HANDLE_EXECUTION_ERROR_GAS\"));\n\n // @dev key for the minimum gas that should be forwarded for execution error handling\n bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode(\"MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD\"));\n\n // @dev key for the min additional gas for execution\n bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode(\"MIN_ADDITIONAL_GAS_FOR_EXECUTION\"));\n\n // @dev for a global reentrancy guard\n bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode(\"REENTRANCY_GUARD_STATUS\"));\n\n // @dev key for deposit fees\n bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode(\"DEPOSIT_FEE_TYPE\"));\n // @dev key for withdrawal fees\n bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\"WITHDRAWAL_FEE_TYPE\"));\n // @dev key for swap fees\n bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode(\"SWAP_FEE_TYPE\"));\n bytes32 public constant ATOMIC_SWAP_FEE_TYPE = keccak256(abi.encode(\"ATOMIC_SWAP_FEE_TYPE\"));\n // @dev key for position fees\n bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode(\"POSITION_FEE_TYPE\"));\n // @dev key for ui deposit fees\n bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode(\"UI_DEPOSIT_FEE_TYPE\"));\n // @dev key for ui withdrawal fees\n bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode(\"UI_WITHDRAWAL_FEE_TYPE\"));\n // @dev key for ui swap fees\n bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode(\"UI_SWAP_FEE_TYPE\"));\n // @dev key for ui position fees\n bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode(\"UI_POSITION_FEE_TYPE\"));\n\n // @dev key for ui fee factor\n bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode(\"UI_FEE_FACTOR\"));\n // @dev key for max ui fee receiver factor\n bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode(\"MAX_UI_FEE_FACTOR\"));\n\n // @dev key for the claimable fee amount\n bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode(\"CLAIMABLE_FEE_AMOUNT\"));\n // @dev key for the claimable ui fee amount\n bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode(\"CLAIMABLE_UI_FEE_AMOUNT\"));\n // @dev key for the max number of auto cancel orders\n bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\"MAX_AUTO_CANCEL_ORDERS\"));\n // @dev key for the max total callback gas limit for auto cancel orders\n bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode(\"MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS\"));\n\n // @dev key for the market list\n bytes32 public constant MARKET_LIST = keccak256(abi.encode(\"MARKET_LIST\"));\n\n // @dev key for the fee batch list\n bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode(\"FEE_BATCH_LIST\"));\n\n // @dev key for the deposit list\n bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode(\"DEPOSIT_LIST\"));\n // @dev key for the account deposit list\n bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode(\"ACCOUNT_DEPOSIT_LIST\"));\n\n // @dev key for the withdrawal list\n bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode(\"WITHDRAWAL_LIST\"));\n // @dev key for the account withdrawal list\n bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode(\"ACCOUNT_WITHDRAWAL_LIST\"));\n\n // @dev key for the shift list\n bytes32 public constant SHIFT_LIST = keccak256(abi.encode(\"SHIFT_LIST\"));\n // @dev key for the account shift list\n bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode(\"ACCOUNT_SHIFT_LIST\"));\n\n bytes32 public constant GLV_LIST = keccak256(abi.encode(\"GLV_LIST\"));\n bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode(\"GLV_DEPOSIT_LIST\"));\n bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode(\"GLV_SHIFT_LIST\"));\n bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode(\"ACCOUNT_GLV_DEPOSIT_LIST\"));\n bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\"GLV_WITHDRAWAL_LIST\"));\n bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode(\"ACCOUNT_GLV_WITHDRAWAL_LIST\"));\n bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode(\"GLV_SUPPORTED_MARKET_LIST\"));\n\n // @dev key for the position list\n bytes32 public constant POSITION_LIST = keccak256(abi.encode(\"POSITION_LIST\"));\n // @dev key for the account position list\n bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode(\"ACCOUNT_POSITION_LIST\"));\n\n // @dev key for the order list\n bytes32 public constant ORDER_LIST = keccak256(abi.encode(\"ORDER_LIST\"));\n // @dev key for the account order list\n bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode(\"ACCOUNT_ORDER_LIST\"));\n\n // @dev key for the subaccount list\n bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode(\"SUBACCOUNT_LIST\"));\n\n // @dev key for the auto cancel order list\n bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode(\"AUTO_CANCEL_ORDER_LIST\"));\n\n // @dev key for is market disabled\n bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode(\"IS_MARKET_DISABLED\"));\n\n // @dev key for the max swap path length allowed\n bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode(\"MAX_SWAP_PATH_LENGTH\"));\n // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets\n bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode(\"SWAP_PATH_MARKET_FLAG\"));\n // @dev key used to store the min market tokens for the first deposit for a market\n bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\"MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT\"));\n\n bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_GLV_DEPOSIT_FEATURE_DISABLED\"));\n bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\"CANCEL_GLV_DEPOSIT_FEATURE_DISABLED\"));\n bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED\"));\n\n bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED\"));\n bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED\"));\n bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED\"));\n\n bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_GLV_SHIFT_FEATURE_DISABLED\"));\n bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_GLV_SHIFT_FEATURE_DISABLED\"));\n\n // @dev key for whether the create deposit feature is disabled\n bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_DEPOSIT_FEATURE_DISABLED\"));\n // @dev key for whether the cancel deposit feature is disabled\n bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\"CANCEL_DEPOSIT_FEATURE_DISABLED\"));\n // @dev key for whether the execute deposit feature is disabled\n bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_DEPOSIT_FEATURE_DISABLED\"));\n\n // @dev key for whether the create withdrawal feature is disabled\n bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_WITHDRAWAL_FEATURE_DISABLED\"));\n // @dev key for whether the cancel withdrawal feature is disabled\n bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"CANCEL_WITHDRAWAL_FEATURE_DISABLED\"));\n // @dev key for whether the execute withdrawal feature is disabled\n bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_WITHDRAWAL_FEATURE_DISABLED\"));\n // @dev key for whether the execute atomic withdrawal feature is disabled\n bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED\"));\n\n // @dev key for whether the create shift feature is disabled\n bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_SHIFT_FEATURE_DISABLED\"));\n // @dev key for whether the cancel shift feature is disabled\n bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\"CANCEL_SHIFT_FEATURE_DISABLED\"));\n // @dev key for whether the execute shift feature is disabled\n bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_SHIFT_FEATURE_DISABLED\"));\n\n // @dev key for whether the create order feature is disabled\n bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\"CREATE_ORDER_FEATURE_DISABLED\"));\n // @dev key for whether the execute order feature is disabled\n bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_ORDER_FEATURE_DISABLED\"));\n // @dev key for whether the execute adl feature is disabled\n // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation\n // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it\n bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode(\"EXECUTE_ADL_FEATURE_DISABLED\"));\n // @dev key for whether the update order feature is disabled\n bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\"UPDATE_ORDER_FEATURE_DISABLED\"));\n // @dev key for whether the cancel order feature is disabled\n bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode(\"CANCEL_ORDER_FEATURE_DISABLED\"));\n\n bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode(\"CLAIM_FUNDING_FEES_FEATURE_DISABLED\"));\n bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode(\"CLAIM_COLLATERAL_FEATURE_DISABLED\"));\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode(\"CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED\"));\n bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode(\"CLAIM_UI_FEES_FEATURE_DISABLED\"));\n bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode(\"SUBACCOUNT_FEATURE_DISABLED\"));\n bytes32 public constant GASLESS_FEATURE_DISABLED = keccak256(abi.encode(\"GASLESS_FEATURE_DISABLED\"));\n bytes32 public constant GENERAL_CLAIM_FEATURE_DISABLED = keccak256(abi.encode(\"GENERAL_CLAIM_FEATURE_DISABLED\"));\n\n // @dev key for the minimum required oracle signers for an oracle observation\n bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode(\"MIN_ORACLE_SIGNERS\"));\n // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation\n bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode(\"MIN_ORACLE_BLOCK_CONFIRMATIONS\"));\n // @dev key for the maximum usable oracle price age in seconds\n bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode(\"MAX_ORACLE_PRICE_AGE\"));\n // @dev key for the maximum usable atomic oracle price age in seconds\n bytes32 public constant MAX_ATOMIC_ORACLE_PRICE_AGE = keccak256(abi.encode(\"MAX_ATOMIC_ORACLE_PRICE_AGE\"));\n // @dev key for the maximum oracle timestamp range\n bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode(\"MAX_ORACLE_TIMESTAMP_RANGE\"));\n // @dev key for the maximum oracle price deviation factor from the ref price\n bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode(\"MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR\"));\n // @dev key for whether an oracle provider is enabled\n bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode(\"IS_ORACLE_PROVIDER_ENABLED\"));\n // @dev key for whether an oracle provider can be used for atomic actions\n bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode(\"IS_ATOMIC_ORACLE_PROVIDER\"));\n // @dev key for oracle timestamp adjustment\n bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode(\"ORACLE_TIMESTAMP_ADJUSTMENT\"));\n // @dev key for oracle provider for token\n bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode(\"ORACLE_PROVIDER_FOR_TOKEN\"));\n // @dev key for oracle provider updated time\n bytes32 public constant ORACLE_PROVIDER_UPDATED_AT = keccak256(abi.encode(\"ORACLE_PROVIDER_UPDATED_AT\"));\n // @dev key for oracle provider same value delay\n bytes32 public constant ORACLE_PROVIDER_MIN_CHANGE_DELAY = keccak256(abi.encode(\"ORACLE_PROVIDER_MIN_CHANGE_DELAY\"));\n // @dev key for the chainlink payment token\n bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode(\"CHAINLINK_PAYMENT_TOKEN\"));\n // @dev key for the sequencer grace duration\n bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode(\"SEQUENCER_GRACE_DURATION\"));\n\n // @dev key for the percentage amount of position fees to be received\n bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\"POSITION_FEE_RECEIVER_FACTOR\"));\n // @dev key for the percentage amount of liquidation fees to be received\n bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\"LIQUIDATION_FEE_RECEIVER_FACTOR\"));\n // @dev key for the percentage amount of swap fees to be received\n bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\"SWAP_FEE_RECEIVER_FACTOR\"));\n // @dev key for the percentage amount of borrowing fees to be received\n bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode(\"BORROWING_FEE_RECEIVER_FACTOR\"));\n\n // @dev key for the base gas limit used when estimating execution fee\n bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\"ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1\"));\n // @dev key for the gas limit used for each oracle price when estimating execution fee\n bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\"ESTIMATED_GAS_FEE_PER_ORACLE_PRICE\"));\n // @dev key for the multiplier used when estimating execution fee\n bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\"ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR\"));\n\n // @dev key for the base gas limit used when calculating execution fee\n bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode(\"EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1\"));\n // @dev key for the gas limit used for each oracle price\n bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode(\"EXECUTION_GAS_FEE_PER_ORACLE_PRICE\"));\n // @dev key for the multiplier used when calculating execution fee\n bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\"EXECUTION_GAS_FEE_MULTIPLIER_FACTOR\"));\n\n // @dev key for the max execution fee multiplier\n bytes32 public constant MAX_EXECUTION_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\"MAX_EXECUTION_FEE_MULTIPLIER_FACTOR\"));\n\n bytes32 public constant MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT = keccak256(abi.encode(\"MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT\"));\n bytes32 public constant GELATO_RELAY_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode(\"GELATO_RELAY_FEE_MULTIPLIER_FACTOR\"));\n bytes32 public constant GELATO_RELAY_FEE_BASE_AMOUNT = keccak256(abi.encode(\"GELATO_RELAY_FEE_BASE_AMOUNT\"));\n bytes32 public constant CREATE_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\"CREATE_DEPOSIT_GAS_LIMIT\"));\n bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\"DEPOSIT_GAS_LIMIT\"));\n bytes32 public constant CREATE_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\"CREATE_WITHDRAWAL_GAS_LIMIT\"));\n bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\"WITHDRAWAL_GAS_LIMIT\"));\n bytes32 public constant CREATE_GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\"CREATE_GLV_DEPOSIT_GAS_LIMIT\"));\n bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode(\"GLV_DEPOSIT_GAS_LIMIT\"));\n bytes32 public constant CREATE_GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\"CREATE_GLV_WITHDRAWAL_GAS_LIMIT\"));\n bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode(\"GLV_WITHDRAWAL_GAS_LIMIT\"));\n bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode(\"GLV_SHIFT_GAS_LIMIT\"));\n bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode(\"GLV_PER_MARKET_GAS_LIMIT\"));\n bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode(\"SHIFT_GAS_LIMIT\"));\n bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode(\"SINGLE_SWAP_GAS_LIMIT\"));\n bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\"INCREASE_ORDER_GAS_LIMIT\"));\n bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode(\"DECREASE_ORDER_GAS_LIMIT\"));\n bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode(\"SWAP_ORDER_GAS_LIMIT\"));\n bytes32 public constant SET_TRADER_REFERRAL_CODE_GAS_LIMIT = keccak256(abi.encode(\"SET_TRADER_REFERRAL_CODE_GAS_LIMIT\"));\n\n bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\"TOKEN_TRANSFER_GAS_LIMIT\"));\n bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode(\"NATIVE_TOKEN_TRANSFER_GAS_LIMIT\"));\n\n bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode(\"REQUEST_EXPIRATION_TIME\"));\n\n bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"MAX_CALLBACK_GAS_LIMIT\"));\n bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode(\"REFUND_EXECUTION_FEE_GAS_LIMIT\"));\n bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode(\"SAVED_CALLBACK_CONTRACT\"));\n\n // @dev key for the min collateral factor\n bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode(\"MIN_COLLATERAL_FACTOR\"));\n // @dev key for the min collateral factor for open interest multiplier\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode(\"MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER\"));\n // @dev key for the min allowed collateral in USD\n bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode(\"MIN_COLLATERAL_USD\"));\n // @dev key for the min allowed collateral factor which is using for some new markets to limit allowed leverage\n bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION = keccak256(abi.encode(\"MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION\"));\n // @dev key for the min allowed position size in USD\n bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode(\"MIN_POSITION_SIZE_USD\"));\n\n // @dev key for the virtual id of tokens\n bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode(\"VIRTUAL_TOKEN_ID\"));\n // @dev key for the virtual id of markets\n bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode(\"VIRTUAL_MARKET_ID\"));\n // @dev key for the virtual inventory for swaps\n bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode(\"VIRTUAL_INVENTORY_FOR_SWAPS\"));\n // @dev key for the virtual inventory for positions\n bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode(\"VIRTUAL_INVENTORY_FOR_POSITIONS\"));\n\n // @dev key for the position impact factor\n bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode(\"POSITION_IMPACT_FACTOR\"));\n // @dev key for the position impact exponent factor\n bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\"POSITION_IMPACT_EXPONENT_FACTOR\"));\n // @dev key for the max decrease position impact factor\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode(\"MAX_POSITION_IMPACT_FACTOR\"));\n // @dev key for the max position impact factor for liquidations\n bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode(\"MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS\"));\n // @dev key for the position fee factor\n bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode(\"POSITION_FEE_FACTOR\"));\n bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode(\"PRO_TRADER_TIER\"));\n bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode(\"PRO_DISCOUNT_FACTOR\"));\n // @dev key for the liquidation fee factor\n bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode(\"LIQUIDATION_FEE_FACTOR\"));\n // @dev key for the swap impact factor\n bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode(\"SWAP_IMPACT_FACTOR\"));\n // @dev key for the swap impact exponent factor\n bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode(\"SWAP_IMPACT_EXPONENT_FACTOR\"));\n // @dev key for the swap fee factor\n bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode(\"SWAP_FEE_FACTOR\"));\n // @dev key for the atomic swap fee factor\n bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode(\"ATOMIC_SWAP_FEE_FACTOR\"));\n bytes32 public constant ATOMIC_WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\"ATOMIC_WITHDRAWAL_FEE_FACTOR\"));\n bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode(\"DEPOSIT_FEE_FACTOR\"));\n bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode(\"WITHDRAWAL_FEE_FACTOR\"));\n // @dev key for the oracle type\n bytes32 public constant ORACLE_TYPE = keccak256(abi.encode(\"ORACLE_TYPE\"));\n // @dev key for open interest\n bytes32 public constant OPEN_INTEREST = keccak256(abi.encode(\"OPEN_INTEREST\"));\n // @dev key for open interest in tokens\n bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode(\"OPEN_INTEREST_IN_TOKENS\"));\n // @dev key for collateral sum for a market\n bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode(\"COLLATERAL_SUM\"));\n // @dev key for pool amount\n bytes32 public constant POOL_AMOUNT = keccak256(abi.encode(\"POOL_AMOUNT\"));\n // @dev key for max pool amount\n bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode(\"MAX_POOL_AMOUNT\"));\n // @dev key for max pool usd for deposit\n bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode(\"MAX_POOL_USD_FOR_DEPOSIT\"));\n // @dev key for max open interest\n bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode(\"MAX_OPEN_INTEREST\"));\n // @dev key for position impact pool amount\n bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\"POSITION_IMPACT_POOL_AMOUNT\"));\n // @dev key for lent position impact pool amount\n bytes32 public constant LENT_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\"LENT_POSITION_IMPACT_POOL_AMOUNT\"));\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR = keccak256(abi.encode(\"MAX_LENDABLE_IMPACT_FACTOR\"));\n bytes32 public constant MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\"MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS\"));\n bytes32 public constant MAX_LENDABLE_IMPACT_USD = keccak256(abi.encode(\"MAX_LENDABLE_IMPACT_USD\"));\n // @dev key for total pending position impact amount\n bytes32 public constant TOTAL_PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\"TOTAL_PENDING_IMPACT_AMOUNT\"));\n // @dev key for min position impact pool amount\n bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\"MIN_POSITION_IMPACT_POOL_AMOUNT\"));\n // @dev key for position impact pool distribution rate\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode(\"POSITION_IMPACT_POOL_DISTRIBUTION_RATE\"));\n // @dev key for position impact pool distributed at\n bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode(\"POSITION_IMPACT_POOL_DISTRIBUTED_AT\"));\n // @dev key for swap impact pool amount\n bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode(\"SWAP_IMPACT_POOL_AMOUNT\"));\n // @dev key for price feed\n bytes32 public constant PRICE_FEED = keccak256(abi.encode(\"PRICE_FEED\"));\n // @dev key for price feed multiplier\n bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode(\"PRICE_FEED_MULTIPLIER\"));\n // @dev key for price feed heartbeat\n bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode(\"PRICE_FEED_HEARTBEAT_DURATION\"));\n // @dev key for data stream feed id\n bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode(\"DATA_STREAM_ID\"));\n bytes32 public constant EDGE_DATA_STREAM_ID = keccak256(abi.encode(\"EDGE_DATA_STREAM_ID\"));\n bytes32 public constant EDGE_DATA_STREAM_TOKEN_DECIMALS = keccak256(abi.encode(\"EDGE_DATA_STREAM_TOKEN_DECIMALS\"));\n // @dev key for data stream feed multiplier\n bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode(\"DATA_STREAM_MULTIPLIER\"));\n bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode(\"DATA_STREAM_SPREAD_REDUCTION_FACTOR\"));\n // @dev key for stable price\n bytes32 public constant STABLE_PRICE = keccak256(abi.encode(\"STABLE_PRICE\"));\n // @dev key for reserve factor\n bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode(\"RESERVE_FACTOR\"));\n // @dev key for open interest reserve factor\n bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode(\"OPEN_INTEREST_RESERVE_FACTOR\"));\n // @dev key for max pnl factor\n bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode(\"MAX_PNL_FACTOR\"));\n // @dev key for max pnl factor\n bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode(\"MAX_PNL_FACTOR_FOR_TRADERS\"));\n // @dev key for max pnl factor for adl\n bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode(\"MAX_PNL_FACTOR_FOR_ADL\"));\n // @dev key for min pnl factor for adl\n bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode(\"MIN_PNL_FACTOR_AFTER_ADL\"));\n // @dev key for max pnl factor\n bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode(\"MAX_PNL_FACTOR_FOR_DEPOSITS\"));\n // @dev key for max pnl factor for withdrawals\n bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode(\"MAX_PNL_FACTOR_FOR_WITHDRAWALS\"));\n // @dev key for latest ADL at\n bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode(\"LATEST_ADL_AT\"));\n // @dev key for whether ADL is enabled\n bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode(\"IS_ADL_ENABLED\"));\n // @dev key for funding factor\n bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode(\"FUNDING_FACTOR\"));\n // @dev key for funding exponent factor\n bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode(\"FUNDING_EXPONENT_FACTOR\"));\n // @dev key for saved funding factor\n bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\"SAVED_FUNDING_FACTOR_PER_SECOND\"));\n // @dev key for funding increase factor\n bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\"FUNDING_INCREASE_FACTOR_PER_SECOND\"));\n // @dev key for funding decrease factor\n bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode(\"FUNDING_DECREASE_FACTOR_PER_SECOND\"));\n // @dev key for min funding factor\n bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\"MIN_FUNDING_FACTOR_PER_SECOND\"));\n // @dev key for max funding factor\n bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode(\"MAX_FUNDING_FACTOR_PER_SECOND\"));\n // @dev key for threshold for stable funding\n bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode(\"THRESHOLD_FOR_STABLE_FUNDING\"));\n // @dev key for threshold for decrease funding\n bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode(\"THRESHOLD_FOR_DECREASE_FUNDING\"));\n // @dev key for funding fee amount per size\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\"FUNDING_FEE_AMOUNT_PER_SIZE\"));\n // @dev key for claimable funding amount per size\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\"CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\"));\n // @dev key for when funding was last updated at\n bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode(\"FUNDING_UPDATED_AT\"));\n // @dev key for claimable funding amount\n bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode(\"CLAIMABLE_FUNDING_AMOUNT\"));\n // @dev key for claimable collateral amount\n bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode(\"CLAIMABLE_COLLATERAL_AMOUNT\"));\n // @dev key for claimable collateral factor\n bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode(\"CLAIMABLE_COLLATERAL_FACTOR\"));\n // @dev key for claimable collateral reduction factor\n bytes32 public constant CLAIMABLE_COLLATERAL_REDUCTION_FACTOR = keccak256(abi.encode(\"CLAIMABLE_COLLATERAL_REDUCTION_FACTOR\"));\n // @dev key for claimable collateral time divisor\n bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode(\"CLAIMABLE_COLLATERAL_TIME_DIVISOR\"));\n // @dev key for claimable collateral delay\n bytes32 public constant CLAIMABLE_COLLATERAL_DELAY = keccak256(abi.encode(\"CLAIMABLE_COLLATERAL_DELAY\"));\n // @dev key for claimed collateral amount\n bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode(\"CLAIMED_COLLATERAL_AMOUNT\"));\n // @dev key for optimal usage factor\n bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode(\"OPTIMAL_USAGE_FACTOR\"));\n // @dev key for base borrowing factor\n bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode(\"BASE_BORROWING_FACTOR\"));\n // @dev key for above optimal usage borrowing factor\n bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode(\"ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR\"));\n // @dev key for borrowing factor\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\"BORROWING_FACTOR\"));\n // @dev key for borrowing factor\n bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode(\"BORROWING_EXPONENT_FACTOR\"));\n // @dev key for skipping the borrowing factor for the smaller side\n bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode(\"SKIP_BORROWING_FEE_FOR_SMALLER_SIDE\"));\n // @dev key for cumulative borrowing factor\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode(\"CUMULATIVE_BORROWING_FACTOR\"));\n // @dev key for when the cumulative borrowing factor was last updated at\n bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode(\"CUMULATIVE_BORROWING_FACTOR_UPDATED_AT\"));\n // @dev key for total borrowing amount\n bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode(\"TOTAL_BORROWING\"));\n // @dev key for affiliate reward\n bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode(\"MIN_AFFILIATE_REWARD_FACTOR\"));\n bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode(\"AFFILIATE_REWARD\"));\n // @dev key for max allowed subaccount action count\n bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\"MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT\"));\n bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode(\"SUBACCOUNT_EXPIRES_AT\"));\n // @dev key for subaccount action count\n bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode(\"SUBACCOUNT_ACTION_COUNT\"));\n // @dev key for subaccount auto top up amount\n bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode(\"SUBACCOUNT_AUTO_TOP_UP_AMOUNT\"));\n // @dev key for subaccount order action\n bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode(\"SUBACCOUNT_ORDER_ACTION\"));\n // @dev key for subaccount integration id\n bytes32 public constant SUBACCOUNT_INTEGRATION_ID = keccak256(abi.encode(\"SUBACCOUNT_INTEGRATION_ID\"));\n // @dev key for subaccount integration id disabled status\n bytes32 public constant SUBACCOUNT_INTEGRATION_DISABLED = keccak256(abi.encode(\"SUBACCOUNT_INTEGRATION_DISABLED\"));\n // @dev key for fee distributor swap order token index\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode(\"FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX\"));\n // @dev key for fee distributor swap fee batch\n bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode(\"FEE_DISTRIBUTOR_SWAP_FEE_BATCH\"));\n\n bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode(\"GLV_MAX_MARKET_COUNT\"));\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode(\"GLV_MAX_MARKET_TOKEN_BALANCE_USD\"));\n bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode(\"GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT\"));\n bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode(\"IS_GLV_MARKET_DISABLED\"));\n bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\"GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR\"));\n bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode(\"GLV_SHIFT_LAST_EXECUTED_AT\"));\n bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode(\"GLV_SHIFT_MIN_INTERVAL\"));\n bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode(\"MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT\"));\n\n // @dev key for disabling automatic parameter updates via ConfigSyncer\n bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode(\"SYNC_CONFIG_FEATURE_DISABLED\"));\n // @dev key for disabling all parameter updates for a specific market via ConfigSyncer\n bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode(\"SYNC_CONFIG_MARKET_DISABLED\"));\n // @dev key for disabling all updates for a specific parameter via ConfigSyncer\n bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode(\"SYNC_CONFIG_PARAMETER_DISABLED\"));\n // @dev key for disabling all updates for a specific market parameter via ConfigSyncer\n bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode(\"SYNC_CONFIG_MARKET_PARAMETER_DISABLED\"));\n // @dev key for tracking which updateIds have already been applied by ConfigSyncer\n bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode(\"SYNC_CONFIG_UPDATE_COMPLETED\"));\n // @dev key for the latest updateId that has been applied by ConfigSyncer\n bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode(\"SYNC_CONFIG_LATEST_UPDATE_ID\"));\n\n bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode(\"CONTRIBUTOR_ACCOUNT_LIST\"));\n bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode(\"CONTRIBUTOR_TOKEN_LIST\"));\n bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\"CONTRIBUTOR_TOKEN_AMOUNT\"));\n bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode(\"MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT\"));\n bytes32 public constant CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\"CONTRIBUTOR_FUNDING_ACCOUNT\"));\n bytes32 public constant CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT = keccak256(abi.encode(\"CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT\"));\n bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode(\"CONTRIBUTOR_LAST_PAYMENT_AT\"));\n bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode(\"MIN_CONTRIBUTOR_PAYMENT_INTERVAL\"));\n\n // @dev key for the buyback batch amount used when claiming and swapping fees\n bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode(\"BUYBACK_BATCH_AMOUNT\"));\n // @dev key for the buyback available fees\n bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode(\"BUYBACK_AVAILABLE_FEE_AMOUNT\"));\n // @dev key for the buyback gmx fee factor used in calculating fees by GMX/WNT\n bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode(\"BUYBACK_GMX_FACTOR\"));\n // @dev key for the FeeHandler max price impact when buying back fees\n bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode(\"BUYBACK_MAX_PRICE_IMPACT_FACTOR\"));\n // @dev key for the maximum price delay in seconds when buying back fees\n bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode(\"BUYBACK_MAX_PRICE_AGE\"));\n // @dev key for the buyback withdrawable fees\n bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode(\"WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT\"));\n\n // @dev key for user's multichain balance\n bytes32 public constant MULTICHAIN_BALANCE = keccak256(abi.encode(\"MULTICHAIN_BALANCE\"));\n // @dev key for the flag if a multichain provider is enabled\n bytes32 public constant IS_MULTICHAIN_PROVIDER_ENABLED = keccak256(abi.encode(\"IS_MULTICHAIN_PROVIDER_ENABLED\"));\n // @dev key for the flag if a multichain endpoint is enabled\n bytes32 public constant IS_MULTICHAIN_ENDPOINT_ENABLED = keccak256(abi.encode(\"IS_MULTICHAIN_ENDPOINT_ENABLED\"));\n // @dev key for the flag if the relay fee is excluded for the caller\n bytes32 public constant IS_RELAY_FEE_EXCLUDED = keccak256(abi.encode(\"IS_RELAY_FEE_EXCLUDED\"));\n // @dev key for the flag if a src chain is enabled\n bytes32 public constant IS_SRC_CHAIN_ID_ENABLED = keccak256(abi.encode(\"IS_SRC_CHAIN_ID_ENABLED\"));\n // @dev key for the last src chain id from which the user last managed his position\n bytes32 public constant POSITION_LAST_SRC_CHAIN_ID = keccak256(abi.encode(\"POSITION_LAST_SRC_CHAIN_ID\"));\n // @dev key for the source chain id mapped from the endpoint id\n bytes32 public constant EID_TO_SRC_CHAIN_ID = keccak256(abi.encode(\"EID_TO_SRC_CHAIN_ID\"));\n\n // @dev key for the maximum length for data list array of bytes32\n bytes32 public constant MAX_DATA_LENGTH = keccak256(abi.encode(\"MAX_DATA_LENGTH\"));\n // @dev key for the action data\n bytes32 public constant GMX_DATA_ACTION = keccak256(abi.encode(\"GMX_DATA_ACTION\"));\n // @dev key for the claimable fund amount for a specific account and token\n bytes32 public constant CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\"CLAIMABLE_FUNDS_AMOUNT\"));\n // @dev key for the total claimable amount for a specific token\n bytes32 public constant TOTAL_CLAIMABLE_FUNDS_AMOUNT = keccak256(abi.encode(\"TOTAL_CLAIMABLE_FUNDS_AMOUNT\"));\n // @dev key for the terms for a specific distribution\n bytes32 public constant CLAIM_TERMS = keccak256(abi.encode(\"CLAIM_TERMS\"));\n // @dev key for the terms hash for a specific distribution\n bytes32 public constant CLAIM_TERMS_BACKREF = keccak256(abi.encode(\"CLAIM_TERMS_BACKREF\"));\n\n // @dev constant for user initiated cancel reason\n string public constant USER_INITIATED_CANCEL = \"USER_INITIATED_CANCEL\";\n\n // @dev function used to calculate fullKey for a given market parameter\n // @param baseKey the base key for the market parameter\n // @param data the additional data for the market parameter\n function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {\n if (data.length == 0) {\n return baseKey;\n }\n\n return keccak256(bytes.concat(baseKey, data));\n }\n\n // @dev key for the account deposit list\n // @param account the account for the list\n function accountDepositListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));\n }\n\n // @dev key for the account withdrawal list\n // @param account the account for the list\n function accountWithdrawalListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));\n }\n\n // @dev key for the account shift list\n // @param account the account for the list\n function accountShiftListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));\n }\n\n // @dev key for the account glv deposit list\n // @param account the account for the list\n function accountGlvDepositListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));\n }\n\n // @dev key for the account glv deposit list\n // @param account the account for the list\n function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));\n }\n\n // @dev key for the glv supported market list\n // @param glv the glv for the supported market list\n function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {\n return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));\n }\n\n // @dev key for the account position list\n // @param account the account for the list\n function accountPositionListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));\n }\n\n // @dev key for the account order list\n // @param account the account for the list\n function accountOrderListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));\n }\n\n // @dev key for the subaccount list\n // @param account the account for the list\n function subaccountListKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(SUBACCOUNT_LIST, account));\n }\n\n // @dev key for the auto cancel order list\n // @param position key the position key for the list\n function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {\n return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));\n }\n\n // @dev key for the claimable fee amount\n // @param market the market for the fee\n // @param token the token for the fee\n function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));\n }\n\n // @dev key for the claimable ui fee amount\n // @param market the market for the fee\n // @param token the token for the fee\n // @param account the account that can claim the ui fee\n function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));\n }\n\n // @dev key for the claimable ui fee amount for account\n // @param market the market for the fee\n // @param token the token for the fee\n // @param account the account that can claim the ui fee\n function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));\n }\n\n // @dev key for deposit gas limit\n // @param singleToken whether a single token or pair tokens are being deposited\n // @return key for deposit gas limit\n function depositGasLimitKey() internal pure returns (bytes32) {\n return DEPOSIT_GAS_LIMIT;\n }\n\n // @dev key for withdrawal gas limit\n // @return key for withdrawal gas limit\n function withdrawalGasLimitKey() internal pure returns (bytes32) {\n return WITHDRAWAL_GAS_LIMIT;\n }\n\n // @dev key for shift gas limit\n // @return key for shift gas limit\n function shiftGasLimitKey() internal pure returns (bytes32) {\n return SHIFT_GAS_LIMIT;\n }\n\n function glvDepositGasLimitKey() internal pure returns (bytes32) {\n return GLV_DEPOSIT_GAS_LIMIT;\n }\n\n function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {\n return GLV_WITHDRAWAL_GAS_LIMIT;\n }\n\n function glvShiftGasLimitKey() internal pure returns (bytes32) {\n return GLV_SHIFT_GAS_LIMIT;\n }\n\n function glvPerMarketGasLimitKey() internal pure returns (bytes32) {\n return GLV_PER_MARKET_GAS_LIMIT;\n }\n\n // @dev key for single swap gas limit\n // @return key for single swap gas limit\n function singleSwapGasLimitKey() internal pure returns (bytes32) {\n return SINGLE_SWAP_GAS_LIMIT;\n }\n\n // @dev key for increase order gas limit\n // @return key for increase order gas limit\n function increaseOrderGasLimitKey() internal pure returns (bytes32) {\n return INCREASE_ORDER_GAS_LIMIT;\n }\n\n // @dev key for decrease order gas limit\n // @return key for decrease order gas limit\n function decreaseOrderGasLimitKey() internal pure returns (bytes32) {\n return DECREASE_ORDER_GAS_LIMIT;\n }\n\n // @dev key for swap order gas limit\n // @return key for swap order gas limit\n function swapOrderGasLimitKey() internal pure returns (bytes32) {\n return SWAP_ORDER_GAS_LIMIT;\n }\n\n function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SWAP_PATH_MARKET_FLAG,\n market\n ));\n }\n\n // @dev key for whether create glv deposit is disabled\n // @param the create deposit module\n // @return key for whether create deposit is disabled\n function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_GLV_DEPOSIT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether cancel glv deposit is disabled\n // @param the cancel deposit module\n // @return key for whether cancel deposit is disabled\n function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether execute glv deposit is disabled\n // @param the execute deposit module\n // @return key for whether execute deposit is disabled\n function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether create glv withdrawal is disabled\n // @param the create withdrawal module\n // @return key for whether create withdrawal is disabled\n function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether cancel glv withdrawal is disabled\n // @param the cancel withdrawal module\n // @return key for whether cancel withdrawal is disabled\n function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether execute glv withdrawal is disabled\n // @param the execute withdrawal module\n // @return key for whether execute withdrawal is disabled\n function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_GLV_SHIFT_FEATURE_DISABLED,\n module\n ));\n }\n\n function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_GLV_SHIFT_FEATURE_DISABLED,\n module\n ));\n }\n\n\n // @dev key for whether create deposit is disabled\n // @param the create deposit module\n // @return key for whether create deposit is disabled\n function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_DEPOSIT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether cancel deposit is disabled\n // @param the cancel deposit module\n // @return key for whether cancel deposit is disabled\n function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CANCEL_DEPOSIT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether execute deposit is disabled\n // @param the execute deposit module\n // @return key for whether execute deposit is disabled\n function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_DEPOSIT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether create withdrawal is disabled\n // @param the create withdrawal module\n // @return key for whether create withdrawal is disabled\n function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether cancel withdrawal is disabled\n // @param the cancel withdrawal module\n // @return key for whether cancel withdrawal is disabled\n function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CANCEL_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether execute withdrawal is disabled\n // @param the execute withdrawal module\n // @return key for whether execute withdrawal is disabled\n function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether execute atomic withdrawal is disabled\n // @param the execute atomic withdrawal module\n // @return key for whether execute atomic withdrawal is disabled\n function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether create shift is disabled\n // @param the create shift module\n // @return key for whether create shift is disabled\n function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_SHIFT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether cancel shift is disabled\n // @param the cancel shift module\n // @return key for whether cancel shift is disabled\n function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CANCEL_SHIFT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether execute shift is disabled\n // @param the execute shift module\n // @return key for whether execute shift is disabled\n function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_SHIFT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether create order is disabled\n // @param the create order module\n // @return key for whether create order is disabled\n function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CREATE_ORDER_FEATURE_DISABLED,\n module,\n orderType\n ));\n }\n\n // @dev key for whether execute order is disabled\n // @param the execute order module\n // @return key for whether execute order is disabled\n function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_ORDER_FEATURE_DISABLED,\n module,\n orderType\n ));\n }\n\n // @dev key for whether execute adl is disabled\n // @param the execute adl module\n // @return key for whether execute adl is disabled\n function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EXECUTE_ADL_FEATURE_DISABLED,\n module,\n orderType\n ));\n }\n\n // @dev key for whether update order is disabled\n // @param the update order module\n // @return key for whether update order is disabled\n function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n UPDATE_ORDER_FEATURE_DISABLED,\n module,\n orderType\n ));\n }\n\n // @dev key for whether cancel order is disabled\n // @param the cancel order module\n // @return key for whether cancel order is disabled\n function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CANCEL_ORDER_FEATURE_DISABLED,\n module,\n orderType\n ));\n }\n\n // @dev key for whether claim funding fees is disabled\n // @param the claim funding fees module\n function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIM_FUNDING_FEES_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether claim colltareral is disabled\n // @param the claim funding fees module\n function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIM_COLLATERAL_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether claim affiliate rewards is disabled\n // @param the claim affiliate rewards module\n function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether claim ui fees is disabled\n // @param the claim ui fees module\n function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIM_UI_FEES_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether subaccounts are disabled\n // @param the subaccount module\n function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SUBACCOUNT_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether subaccounts are disabled\n // @param the gasless module\n function gaslessFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n GASLESS_FEATURE_DISABLED,\n module\n ));\n }\n\n function generalClaimFeatureDisabled(uint256 distributionId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n GENERAL_CLAIM_FEATURE_DISABLED,\n distributionId\n ));\n }\n\n // @dev key for ui fee factor\n // @param account the fee receiver account\n // @return key for ui fee factor\n function uiFeeFactorKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n UI_FEE_FACTOR,\n account\n ));\n }\n\n // @dev key for whether an oracle provider is enabled\n // @param provider the oracle provider\n // @return key for whether an oracle provider is enabled\n function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_ORACLE_PROVIDER_ENABLED,\n provider\n ));\n }\n\n // @dev key for whether an oracle provider is allowed to be used for atomic actions\n // @param provider the oracle provider\n // @return key for whether an oracle provider is allowed to be used for atomic actions\n function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_ATOMIC_ORACLE_PROVIDER,\n provider\n ));\n }\n\n // @dev key for oracle timestamp adjustment\n // @param provider the oracle provider\n // @param token the token\n // @return key for oracle timestamp adjustment\n function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ORACLE_TIMESTAMP_ADJUSTMENT,\n provider,\n token\n ));\n }\n\n // @dev key for oracle provider for token\n // @param token the token\n // @return key for oracle provider for token\n function oracleProviderForTokenKey(address oracle, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ORACLE_PROVIDER_FOR_TOKEN,\n oracle,\n token\n ));\n }\n\n // @dev key for oracle provider update time\n // @param token the token\n // @param provider address\n // @return key for oracle provider updated time\n function oracleProviderUpdatedAt(address token, address provider) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ORACLE_PROVIDER_UPDATED_AT,\n token,\n provider\n ));\n }\n\n // @dev key for gas to forward for token transfer\n // @param the token to check\n // @return key for gas to forward for token transfer\n function tokenTransferGasLimit(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n TOKEN_TRANSFER_GAS_LIMIT,\n token\n ));\n }\n\n // @dev the default callback contract\n // @param account the user's account\n // @param market the address of the market\n // @param callbackContract the callback contract\n function savedCallbackContract(address account, address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SAVED_CALLBACK_CONTRACT,\n account,\n market\n ));\n }\n\n // @dev the min collateral factor key\n // @param the market for the min collateral factor\n function minCollateralFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_COLLATERAL_FACTOR,\n market\n ));\n }\n\n // @dev the min collateral factor for open interest multiplier key\n // @param the market for the factor\n function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,\n market,\n isLong\n ));\n }\n\n // @dev the min collateral factor for open interest multiplier key\n // @param the market for the factor\n function minCollateralFactorForLiquidationKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_COLLATERAL_FACTOR_FOR_LIQUIDATION,\n market\n ));\n }\n\n // @dev the key for the virtual token id\n // @param the token to get the virtual id for\n function virtualTokenIdKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n VIRTUAL_TOKEN_ID,\n token\n ));\n }\n\n // @dev the key for the virtual market id\n // @param the market to get the virtual id for\n function virtualMarketIdKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n VIRTUAL_MARKET_ID,\n market\n ));\n }\n\n // @dev the key for the virtual inventory for positions\n // @param the virtualTokenId the virtual token id\n function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n VIRTUAL_INVENTORY_FOR_POSITIONS,\n virtualTokenId\n ));\n }\n\n // @dev the key for the virtual inventory for swaps\n // @param the virtualMarketId the virtual market id\n // @param the token to check the inventory for\n function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n VIRTUAL_INVENTORY_FOR_SWAPS,\n virtualMarketId,\n isLongToken\n ));\n }\n\n // @dev key for position impact factor\n // @param market the market address to check\n // @param isPositive whether the impact is positive or negative\n // @return key for position impact factor\n function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_IMPACT_FACTOR,\n market,\n isPositive\n ));\n }\n\n // @dev key for position impact exponent factor\n // @param market the market address to check\n // @return key for position impact exponent factor\n function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_IMPACT_EXPONENT_FACTOR,\n market\n ));\n }\n\n // @dev key for the max position impact factor\n // @param market the market address to check\n // @return key for the max position impact factor\n function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_POSITION_IMPACT_FACTOR,\n market,\n isPositive\n ));\n }\n\n // @dev key for the max position impact factor for liquidations\n // @param market the market address to check\n // @return key for the max position impact factor\n function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,\n market\n ));\n }\n\n // @dev key for position fee factor\n // @param market the market address to check\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\n // @return key for position fee factor\n function positionFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_FEE_FACTOR,\n market,\n balanceWasImproved\n ));\n }\n\n // @dev key for pro trader's tier\n function proTraderTierKey(address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n PRO_TRADER_TIER,\n account\n ));\n }\n\n\n // @dev key for pro discount factor for specific tier\n function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n PRO_DISCOUNT_FACTOR,\n proTier\n ));\n }\n\n // @dev key for liquidation fee factor\n // @param market the market address to check\n // @return key for liquidation fee factor\n function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n LIQUIDATION_FEE_FACTOR,\n market\n ));\n }\n\n // @dev key for swap impact factor\n // @param market the market address to check\n // @param isPositive whether the impact is positive or negative\n // @return key for swap impact factor\n function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SWAP_IMPACT_FACTOR,\n market,\n isPositive\n ));\n }\n\n // @dev key for swap impact exponent factor\n // @param market the market address to check\n // @return key for swap impact exponent factor\n function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SWAP_IMPACT_EXPONENT_FACTOR,\n market\n ));\n }\n\n\n // @dev key for swap fee factor\n // @param market the market address to check\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\n // @return key for swap fee factor\n function swapFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SWAP_FEE_FACTOR,\n market,\n balanceWasImproved\n ));\n }\n\n // @dev key for atomic swap fee factor\n // @param market the market address to check\n // @return key for atomic swap fee factor\n function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ATOMIC_SWAP_FEE_FACTOR,\n market\n ));\n }\n\n // @dev key for atomic withdrawal fee factor\n // @param market the market address to check\n // @return key for atomic withdrawal fee factor\n function atomicWithdrawalFeeFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ATOMIC_WITHDRAWAL_FEE_FACTOR,\n market\n ));\n }\n\n // @dev key for deposit fee factor\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\n // @return key for deposit fee factor\n function depositFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n DEPOSIT_FEE_FACTOR,\n market,\n balanceWasImproved\n ));\n }\n\n // @dev key for withdrawal fee factor\n // @param market the market address to check\n // @param balanceWasImproved whether the fee is for an action that has improved the balance\n // @return key for withdrawal fee factor\n function withdrawalFeeFactorKey(address market, bool balanceWasImproved) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n WITHDRAWAL_FEE_FACTOR,\n market,\n balanceWasImproved\n ));\n }\n\n // @dev key for oracle type\n // @param token the token to check\n // @return key for oracle type\n function oracleTypeKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ORACLE_TYPE,\n token\n ));\n }\n\n // @dev key for open interest\n // @param market the market to check\n // @param collateralToken the collateralToken to check\n // @param isLong whether to check the long or short open interest\n // @return key for open interest\n function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n OPEN_INTEREST,\n market,\n collateralToken,\n isLong\n ));\n }\n\n // @dev key for open interest in tokens\n // @param market the market to check\n // @param collateralToken the collateralToken to check\n // @param isLong whether to check the long or short open interest\n // @return key for open interest in tokens\n function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n OPEN_INTEREST_IN_TOKENS,\n market,\n collateralToken,\n isLong\n ));\n }\n\n // @dev key for collateral sum for a market\n // @param market the market to check\n // @param collateralToken the collateralToken to check\n // @param isLong whether to check the long or short open interest\n // @return key for collateral sum\n function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n COLLATERAL_SUM,\n market,\n collateralToken,\n isLong\n ));\n }\n\n // @dev key for amount of tokens in a market's pool\n // @param market the market to check\n // @param token the token to check\n // @return key for amount of tokens in a market's pool\n function poolAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POOL_AMOUNT,\n market,\n token\n ));\n }\n\n // @dev the key for the max amount of pool tokens\n // @param market the market for the pool\n // @param token the token for the pool\n function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_POOL_AMOUNT,\n market,\n token\n ));\n }\n\n // @dev the key for the max usd of pool tokens for deposits\n // @param market the market for the pool\n // @param token the token for the pool\n function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_POOL_USD_FOR_DEPOSIT,\n market,\n token\n ));\n }\n\n // @dev the key for the max open interest\n // @param market the market for the pool\n // @param isLong whether the key is for the long or short side\n function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_OPEN_INTEREST,\n market,\n isLong\n ));\n }\n\n // @dev key for amount of tokens in a market's position impact pool\n // @param market the market to check\n // @return key for amount of tokens in a market's position impact pool\n function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_IMPACT_POOL_AMOUNT,\n market\n ));\n }\n\n function lentPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n LENT_POSITION_IMPACT_POOL_AMOUNT,\n market\n ));\n }\n\n function maxLendableImpactFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_LENDABLE_IMPACT_FACTOR,\n market\n ));\n }\n\n function maxLendableImpactFactorForWithdrawalsKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_LENDABLE_IMPACT_FACTOR_FOR_WITHDRAWALS,\n market\n ));\n }\n\n function maxLendableImpactUsdKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_LENDABLE_IMPACT_USD,\n market\n ));\n }\n\n function totalPendingImpactAmountKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n TOTAL_PENDING_IMPACT_AMOUNT,\n market\n ));\n }\n\n // @dev key for min amount of tokens in a market's position impact pool\n // @param market the market to check\n // @return key for min amount of tokens in a market's position impact pool\n function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_POSITION_IMPACT_POOL_AMOUNT,\n market\n ));\n }\n\n // @dev key for position impact pool distribution rate\n // @param market the market to check\n // @return key for position impact pool distribution rate\n function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_IMPACT_POOL_DISTRIBUTION_RATE,\n market\n ));\n }\n\n // @dev key for position impact pool distributed at\n // @param market the market to check\n // @return key for position impact pool distributed at\n function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_IMPACT_POOL_DISTRIBUTED_AT,\n market\n ));\n }\n\n // @dev key for amount of tokens in a market's swap impact pool\n // @param market the market to check\n // @param token the token to check\n // @return key for amount of tokens in a market's swap impact pool\n function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SWAP_IMPACT_POOL_AMOUNT,\n market,\n token\n ));\n }\n\n // @dev key for reserve factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for reserve factor\n function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n RESERVE_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for open interest reserve factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for open interest reserve factor\n function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n OPEN_INTEREST_RESERVE_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for max pnl factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for max pnl factor\n function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_PNL_FACTOR,\n pnlFactorType,\n market,\n isLong\n ));\n }\n\n // @dev the key for min PnL factor after ADL\n // @param market the market for the pool\n // @param isLong whether the key is for the long or short side\n function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_PNL_FACTOR_AFTER_ADL,\n market,\n isLong\n ));\n }\n\n // @dev key for latest adl time\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for latest adl time\n function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n LATEST_ADL_AT,\n market,\n isLong\n ));\n }\n\n // @dev key for whether adl is enabled\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for whether adl is enabled\n function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_ADL_ENABLED,\n market,\n isLong\n ));\n }\n\n // @dev key for funding factor\n // @param market the market to check\n // @return key for funding factor\n function fundingFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FUNDING_FACTOR,\n market\n ));\n }\n\n // @dev the key for funding exponent\n // @param market the market for the pool\n function fundingExponentFactorKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FUNDING_EXPONENT_FACTOR,\n market\n ));\n }\n\n // @dev the key for saved funding factor\n // @param market the market for the pool\n function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SAVED_FUNDING_FACTOR_PER_SECOND,\n market\n ));\n }\n\n // @dev the key for funding increase factor\n // @param market the market for the pool\n function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FUNDING_INCREASE_FACTOR_PER_SECOND,\n market\n ));\n }\n\n // @dev the key for funding decrease factor\n // @param market the market for the pool\n function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FUNDING_DECREASE_FACTOR_PER_SECOND,\n market\n ));\n }\n\n // @dev the key for min funding factor\n // @param market the market for the pool\n function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_FUNDING_FACTOR_PER_SECOND,\n market\n ));\n }\n\n // @dev the key for max funding factor\n // @param market the market for the pool\n function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_FUNDING_FACTOR_PER_SECOND,\n market\n ));\n }\n\n // @dev the key for threshold for stable funding\n // @param market the market for the pool\n function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n THRESHOLD_FOR_STABLE_FUNDING,\n market\n ));\n }\n\n // @dev the key for threshold for decreasing funding\n // @param market the market for the pool\n function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n THRESHOLD_FOR_DECREASE_FUNDING,\n market\n ));\n }\n\n // @dev key for funding fee amount per size\n // @param market the market to check\n // @param collateralToken the collateralToken to get the key for\n // @param isLong whether to get the key for the long or short side\n // @return key for funding fee amount per size\n function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FUNDING_FEE_AMOUNT_PER_SIZE,\n market,\n collateralToken,\n isLong\n ));\n }\n\n // @dev key for claimabel funding amount per size\n // @param market the market to check\n // @param collateralToken the collateralToken to get the key for\n // @param isLong whether to get the key for the long or short side\n // @return key for claimable funding amount per size\n function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,\n market,\n collateralToken,\n isLong\n ));\n }\n\n // @dev key for when funding was last updated\n // @param market the market to check\n // @return key for when funding was last updated\n function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FUNDING_UPDATED_AT,\n market\n ));\n }\n\n // @dev key for claimable funding amount\n // @param market the market to check\n // @param token the token to check\n // @return key for claimable funding amount\n function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_FUNDING_AMOUNT,\n market,\n token\n ));\n }\n\n // @dev key for claimable funding amount by account\n // @param market the market to check\n // @param token the token to check\n // @param account the account to check\n // @return key for claimable funding amount\n function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_FUNDING_AMOUNT,\n market,\n token,\n account\n ));\n }\n\n // @dev key for claimable collateral amount\n // @param market the market to check\n // @param token the token to check\n // @param account the account to check\n // @param timeKey the time key for the claimable amount\n // @return key for claimable funding amount\n function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_COLLATERAL_AMOUNT,\n market,\n token\n ));\n }\n\n // @dev key for claimable collateral amount for a timeKey for an account\n // @param market the market to check\n // @param token the token to check\n // @param account the account to check\n // @param timeKey the time key for the claimable amount\n // @return key for claimable funding amount\n function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_COLLATERAL_AMOUNT,\n market,\n token,\n timeKey,\n account\n ));\n }\n\n // @dev key for claimable collateral factor for a timeKey\n // @param market the market to check\n // @param token the token to check\n // @param timeKey the time key for the claimable amount\n // @return key for claimable funding amount\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_COLLATERAL_FACTOR,\n market,\n token,\n timeKey\n ));\n }\n\n // @dev key for claimable collateral factor for a timeKey for an account\n // @param market the market to check\n // @param token the token to check\n // @param timeKey the time key for the claimable amount\n // @param account the account to check\n // @return key for claimable funding amount\n function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_COLLATERAL_FACTOR,\n market,\n token,\n timeKey,\n account\n ));\n }\n\n // @dev key for claimable collateral reduction factor for a timeKey for an account\n // @param market the market to check\n // @param token the token to check\n // @param timeKey the time key for the claimable factor\n // @param account the account to check\n // @return key for claimable funding factor\n function claimableCollateralReductionFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_COLLATERAL_REDUCTION_FACTOR,\n market,\n token,\n timeKey,\n account\n ));\n }\n\n // @dev key for claimable collateral factor\n // @param market the market to check\n // @param token the token to check\n // @param account the account to check\n // @param timeKey the time key for the claimable amount\n // @return key for claimable funding amount\n function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMED_COLLATERAL_AMOUNT,\n market,\n token,\n timeKey,\n account\n ));\n }\n\n // @dev key for optimal usage factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for optimal usage factor\n function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n OPTIMAL_USAGE_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for base borrowing factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for base borrowing factor\n function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BASE_BORROWING_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for above optimal usage borrowing factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for above optimal usage borrowing factor\n function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for borrowing factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for borrowing factor\n function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BORROWING_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev the key for borrowing exponent\n // @param market the market for the pool\n // @param isLong whether to get the key for the long or short side\n function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BORROWING_EXPONENT_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for cumulative borrowing factor\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for cumulative borrowing factor\n function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CUMULATIVE_BORROWING_FACTOR,\n market,\n isLong\n ));\n }\n\n // @dev key for cumulative borrowing factor updated at\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for cumulative borrowing factor updated at\n function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,\n market,\n isLong\n ));\n }\n\n // @dev key for total borrowing amount\n // @param market the market to check\n // @param isLong whether to get the key for the long or short side\n // @return key for total borrowing amount\n function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n TOTAL_BORROWING,\n market,\n isLong\n ));\n }\n\n // @dev key for affiliate reward amount\n // @param market the market to check\n // @param token the token to get the key for\n // @param account the account to get the key for\n // @return key for affiliate reward amount\n function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n AFFILIATE_REWARD,\n market,\n token\n ));\n }\n\n function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_AFFILIATE_REWARD_FACTOR,\n referralTierLevel\n ));\n }\n\n function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,\n account,\n subaccount,\n actionType\n ));\n }\n\n function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SUBACCOUNT_EXPIRES_AT,\n account,\n subaccount,\n actionType\n ));\n }\n\n function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SUBACCOUNT_ACTION_COUNT,\n account,\n subaccount,\n actionType\n ));\n }\n\n function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SUBACCOUNT_AUTO_TOP_UP_AMOUNT,\n account,\n subaccount\n ));\n }\n\n function subaccountIntegrationIdKey(address account, address subaccount) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SUBACCOUNT_INTEGRATION_ID,\n account,\n subaccount\n ));\n }\n\n function subaccountIntegrationDisabledKey(bytes32 integrationId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SUBACCOUNT_INTEGRATION_DISABLED,\n integrationId\n ));\n }\n\n // @dev key for affiliate reward amount for an account\n // @param market the market to check\n // @param token the token to get the key for\n // @param account the account to get the key for\n // @return key for affiliate reward amount\n function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n AFFILIATE_REWARD,\n market,\n token,\n account\n ));\n }\n\n // @dev key for is market disabled\n // @param market the market to check\n // @return key for is market disabled\n function isMarketDisabledKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_MARKET_DISABLED,\n market\n ));\n }\n\n // @dev key for min market tokens for first deposit\n // @param market the market to check\n // @return key for min market tokens for first deposit\n function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,\n market\n ));\n }\n\n // @dev key for price feed address\n // @param token the token to get the key for\n // @return key for price feed address\n function priceFeedKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n PRICE_FEED,\n token\n ));\n }\n\n // @dev key for data stream feed ID\n // @param token the token to get the key for\n // @return key for data stream feed ID\n function dataStreamIdKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n DATA_STREAM_ID,\n token\n ));\n }\n\n function edgeDataStreamIdKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EDGE_DATA_STREAM_ID,\n token\n ));\n }\n\n function edgeDataStreamTokenDecimalsKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EDGE_DATA_STREAM_TOKEN_DECIMALS,\n token\n ));\n }\n\n // @dev key for data stream feed multiplier\n // @param token the token to get the key for\n // @return key for data stream feed multiplier\n function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n DATA_STREAM_MULTIPLIER,\n token\n ));\n }\n\n function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n DATA_STREAM_SPREAD_REDUCTION_FACTOR,\n token\n ));\n }\n\n // @dev key for price feed multiplier\n // @param token the token to get the key for\n // @return key for price feed multiplier\n function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n PRICE_FEED_MULTIPLIER,\n token\n ));\n }\n\n function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n PRICE_FEED_HEARTBEAT_DURATION,\n token\n ));\n }\n\n // @dev key for stable price value\n // @param token the token to get the key for\n // @return key for stable price value\n function stablePriceKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n STABLE_PRICE,\n token\n ));\n }\n\n // @dev key for fee distributor swap token index\n // @param orderKey the swap order key\n // @return key for fee distributor swap token index\n function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,\n orderKey\n ));\n }\n\n // @dev key for fee distributor swap fee batch key\n // @param orderKey the swap order key\n // @return key for fee distributor swap fee batch key\n function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n FEE_DISTRIBUTOR_SWAP_FEE_BATCH,\n orderKey\n ));\n }\n\n // @dev key for max market token balance usd\n // it is used to limit amount of funds deposited into each market\n function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));\n }\n\n // @dev key for max market token balance amount\n // it is used to limit amount of funds deposited into each market\n function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));\n }\n\n // @dev key for is glv market disabled\n function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_GLV_MARKET_DISABLED,\n glv,\n market\n ));\n }\n\n // @dev key for max allowed price impact for glv shifts\n // if effective price impact exceeds max price impact then glv shift fails\n function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,\n glv\n ));\n }\n\n // @dev key for time when glv shift was executed last\n // used to validate glv shifts are not executed too frequently\n function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n GLV_SHIFT_LAST_EXECUTED_AT,\n glv\n ));\n }\n\n // @dev key for min time interval between glv shifts in seconds\n function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n GLV_SHIFT_MIN_INTERVAL,\n glv\n ));\n }\n\n function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,\n glv\n ));\n }\n\n // @dev key for whether the sync config feature is disabled\n // @param module the sync config module\n // @return key for sync config feature disabled\n function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SYNC_CONFIG_FEATURE_DISABLED,\n module\n ));\n }\n\n // @dev key for whether sync config updates are disabled for a market\n // @param market the market to check\n // @return key for sync config market disabled\n function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SYNC_CONFIG_MARKET_DISABLED,\n market\n ));\n }\n\n // @dev key for whether sync config updates are disabled for a parameter\n // @param parameter the parameter to check\n // @return key for sync config parameter disabled\n function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SYNC_CONFIG_PARAMETER_DISABLED,\n parameter\n ));\n }\n\n // @dev key for whether sync config updates are disabled for a market parameter\n // @param market the market to check\n // @param parameter the parameter to check\n // @return key for sync config market parameter disabled\n function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SYNC_CONFIG_MARKET_PARAMETER_DISABLED,\n market,\n parameter\n ));\n }\n\n // @dev key for whether a sync config update is completed\n // @param updateId the update id to check\n // @return key for sync config market update completed\n function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n SYNC_CONFIG_UPDATE_COMPLETED,\n updateId\n ));\n }\n\n // @dev key for the latest sync config update that was completed\n // @return key for sync config latest update id\n function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {\n return SYNC_CONFIG_LATEST_UPDATE_ID;\n }\n\n // @dev key for the contributor token amount\n // @param account the contributor account\n // @param token the contributor token\n // @return key for the contributor token amount\n function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CONTRIBUTOR_TOKEN_AMOUNT,\n account,\n token\n ));\n }\n\n // @dev key for the max total contributor token amount\n // @param token the contributor token\n // @return key for the max contributor token amount\n function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,\n token\n ));\n }\n\n function contributorFundingAccountKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CONTRIBUTOR_FUNDING_ACCOUNT,\n token\n ));\n }\n\n function customContributorFundingAccountKey(address account, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CUSTOM_CONTRIBUTOR_FUNDING_ACCOUNT,\n account,\n token\n ));\n }\n\n // @dev key for the buyback batch amount\n // @param token the token for which to retrieve batch amount (GMX or WNT)\n // @return key for buyback batch amount for a given token\n function buybackBatchAmountKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BUYBACK_BATCH_AMOUNT,\n token\n ));\n }\n\n // @dev key for the buyback available fee amount\n // @param feeToken the token in which the fees are denominated\n // @param swapToken the token for which fees are accumulated (GMX or WNT)\n // @return key for buyback available fee amount for a given token and feeToken\n function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BUYBACK_AVAILABLE_FEE_AMOUNT,\n feeToken,\n swapToken\n ));\n }\n\n // @dev key for the buyback withdrawable fee amount\n // @param buybackToken the token that was bought back\n // @return key for the buyback withdrawable fee amount\n function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,\n buybackToken\n ));\n }\n\n // @dev key for the buyback gmx fee factor\n // @param version the version for which to retrieve the fee numerator\n // @return key for buyback gmx fee factor for a given version\n function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BUYBACK_GMX_FACTOR,\n version\n ));\n }\n\n // @dev key for the buyback max price impact factor\n // @param token the token for which to retrieve the max price impact factor key\n // @return key for buyback max price impact factor for a given token\n function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n BUYBACK_MAX_PRICE_IMPACT_FACTOR,\n token\n ));\n }\n\n // @dev key for whether a multichain provider is enabled\n // @param provider the multichain provider\n // @return key for whether a multichain provider is enabled\n function isMultichainProviderEnabledKey(address provider) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_MULTICHAIN_PROVIDER_ENABLED,\n provider\n ));\n }\n\n // @dev key for whether a multichain endpoint is enabled\n // @param endpoint the multichain endpoint\n // @return key for whether a multichain endpoint is enabled\n function isMultichainEndpointEnabledKey(address endpoint) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_MULTICHAIN_ENDPOINT_ENABLED,\n endpoint\n ));\n }\n\n // @dev key for whether a relay fee is excluded for the caller\n // @param sender the address of the sender\n // @return key for whether a relay fee is excluded\n function isRelayFeeExcludedKey(address sender) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_RELAY_FEE_EXCLUDED,\n sender\n ));\n }\n\n // @dev key for whether a multichain endpoint is enabled\n // @param endpoint the multichain endpoint\n // @return key for whether a multichain endpoint is enabled\n function isSrcChainIdEnabledKey(uint256 srcChainId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n IS_SRC_CHAIN_ID_ENABLED,\n srcChainId\n ));\n }\n\n // @dev key for the last src chain id from which the user last managed his position\n // @param positionKey the position key for which to retrieve the last src chain id\n // @return key for the last src chain id from which the user last managed his position\n function positionLastSrcChainId(bytes32 positionKey) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n POSITION_LAST_SRC_CHAIN_ID,\n positionKey\n ));\n }\n\n // @dev key for the source chain id mapped from the endpoint id\n // @param eid the endpoint id of the source chain\n // @return key for the srcChainId\n function eidToSrcChainId(uint32 eid) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n EID_TO_SRC_CHAIN_ID,\n eid\n ));\n }\n\n // @dev key for user's multichain balance\n // @param account the account for which to retrieve the user balance key\n // @param token the token for which to retrieve the user balance key\n // @return key for multichain balance for a given user and token\n function multichainBalanceKey(address account, address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n MULTICHAIN_BALANCE,\n account,\n token\n ));\n }\n\n // @dev key for the claimable fund amount for a specific account and token\n // @param account the account to claim funds for\n // @param token the token to claim\n // @param distributionId the distribution id to claim funds for\n // @return key for claimable fund amount\n function claimableFundsAmountKey(address account, address token, uint256 distributionId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIMABLE_FUNDS_AMOUNT,\n account,\n token,\n distributionId\n ));\n }\n\n // @dev key for the total claimable amount for a specific token\n // @param token the token for which to retrieve the total claimable amount\n // @return key for total claimable amount\n function totalClaimableFundsAmountKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n TOTAL_CLAIMABLE_FUNDS_AMOUNT,\n token\n ));\n }\n\n function claimTermsKey(uint256 distributionId) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIM_TERMS,\n distributionId\n ));\n }\n\n function claimTermsBackrefKey(bytes32 termsHash) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n CLAIM_TERMS_BACKREF,\n termsHash\n ));\n }\n}\n" + }, + "contracts/data/Keys2.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title Keys2\n// @dev Additional keys for values in the DataStore\nlibrary Keys2 {\n // @dev key for MultichainReader read channel\n bytes32 public constant MULTICHAIN_READ_CHANNEL = keccak256(abi.encode(\"MULTICHAIN_READ_CHANNEL\"));\n // @dev key for MultichainReader read channel to peer mapping\n bytes32 public constant MULTICHAIN_PEERS = keccak256(abi.encode(\"MULTICHAIN_PEERS\"));\n // @dev key for MultichainReader number of confirmations to wait for finality\n bytes32 public constant MULTICHAIN_CONFIRMATIONS = keccak256(abi.encode(\"MULTICHAIN_CONFIRMATIONS\"));\n // @dev key for MultichainReader guid to originator mapping\n bytes32 public constant MULTICHAIN_GUID_TO_ORIGINATOR = keccak256(abi.encode(\"MULTICHAIN_GUID_TO_ORIGINATOR\"));\n // @dev key for MultichainReader authorized orginators\n bytes32 public constant MULTICHAIN_AUTHORIZED_ORIGINATORS = keccak256(abi.encode(\"MULTICHAIN_AUTHORIZED_ORIGINATORS\"));\n\n // @dev key for FeeDistributor day of the week (0 = Sunday, 6 = Saturday)\n bytes32 public constant FEE_DISTRIBUTOR_DISTRIBUTION_DAY = keccak256(abi.encode(\"FEE_DISTRIBUTOR_DISTRIBUTION_DAY\"));\n // @dev key for FeeDistributor timestamp that the last distribution was completed\n bytes32 public constant FEE_DISTRIBUTOR_DISTRIBUTION_TIMESTAMP = keccak256(abi.encode(\"FEE_DISTRIBUTOR_DISTRIBUTION_TIMESTAMP\"));\n // @dev key for the fee distribution state\n bytes32 public constant FEE_DISTRIBUTOR_STATE = keccak256(abi.encode(\"FEE_DISTRIBUTOR_STATE\"));\n // @dev key for FeeDistributor referral rewards for a given token\n bytes32 public constant FEE_DISTRIBUTOR_REFERRAL_REWARDS_AMOUNT = keccak256(abi.encode(\"FEE_DISTRIBUTOR_REFERRAL_REWARDS_AMOUNT\"));\n // @dev key for FeeDistributor max WNT referral awards amount in USD\n bytes32 public constant FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_AMOUNT = keccak256(abi.encode(\"FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_AMOUNT\"));\n // @dev key for FeeDistributor max WNT referral rewards factor in USD\n bytes32 public constant FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_FACTOR = keccak256(abi.encode(\"FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_FACTOR\"));\n // @dev key for FeeDistributor max ESGMX referral awards amount\n bytes32 public constant FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_ESGMX_AMOUNT = keccak256(abi.encode(\"FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_ESGMX_AMOUNT\"));\n // @dev key for FeeDistributor GMX price for referral rewards calculations\n bytes32 public constant FEE_DISTRIBUTOR_GMX_PRICE = keccak256(abi.encode(\"FEE_DISTRIBUTOR_GMX_PRICE\"));\n // @dev key for FeeDistributor WNT price for referral rewards calculations\n bytes32 public constant FEE_DISTRIBUTOR_WNT_PRICE = keccak256(abi.encode(\"FEE_DISTRIBUTOR_WNT_PRICE\"));\n // @dev key for FeeDistributor max read response delay in seconds from MultichainReader\n bytes32 public constant FEE_DISTRIBUTOR_MAX_READ_RESPONSE_DELAY = keccak256(abi.encode(\"FEE_DISTRIBUTOR_MAX_READ_RESPONSE_DELAY\"));\n // @dev key for FeeDistributor gas limit used for the MultichainReader read request\n bytes32 public constant FEE_DISTRIBUTOR_GAS_LIMIT = keccak256(abi.encode(\"FEE_DISTRIBUTOR_GAS_LIMIT\"));\n // @dev key for FeeDistributor chain ID\n bytes32 public constant FEE_DISTRIBUTOR_CHAIN_ID = keccak256(abi.encode(\"FEE_DISTRIBUTOR_CHAIN_ID\"));\n // @dev key for FeeDistributor GMX fee amount for a given chain\n bytes32 public constant FEE_DISTRIBUTOR_FEE_AMOUNT_GMX = keccak256(abi.encode(\"FEE_DISTRIBUTOR_FEE_AMOUNT_GMX\"));\n // @dev key FeeDistributor total GMX fee amount for all chains combined\n bytes32 public constant FEE_DISTRIBUTOR_TOTAL_FEE_AMOUNT_GMX = keccak256(abi.encode(\"FEE_DISTRIBUTOR_TOTAL_FEE_AMOUNT_GMX\"));\n // @dev key for FeeDistributor total fee amount in USD by version\n bytes32 public constant FEE_DISTRIBUTOR_FEE_AMOUNT_USD = keccak256(abi.encode(\"FEE_DISTRIBUTOR_FEE_AMOUNT_USD\"));\n // @dev key for FeeDistributor staked GMX for a given chain\n bytes32 public constant FEE_DISTRIBUTOR_STAKED_GMX = keccak256(abi.encode(\"FEE_DISTRIBUTOR_STAKED_GMX\"));\n // @dev key FeeDistributor total staked GMX for all chains combined\n bytes32 public constant FEE_DISTRIBUTOR_TOTAL_STAKED_GMX = keccak256(abi.encode(\"FEE_DISTRIBUTOR_TOTAL_STAKED_GMX\"));\n // @dev key for FeeDistributor bridging slippage factor\n bytes32 public constant FEE_DISTRIBUTOR_BRIDGE_SLIPPAGE_FACTOR = keccak256(abi.encode(\"FEE_DISTRIBUTOR_BRIDGE_SLIPPAGE_FACTOR\"));\n // @dev key for FeeDistributor read response timestamp\n bytes32 public constant FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP = keccak256(abi.encode(\"FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP\"));\n // @dev key for FeeDistributor LayerZero version of chainId\n bytes32 public constant FEE_DISTRIBUTOR_LAYERZERO_CHAIN_ID = keccak256(abi.encode(\"FEE_DISTRIBUTOR_LAYERZERO_CHAIN_ID\"));\n // @dev key for contract and keeper addresses stored used in FeeDistributor\n bytes32 public constant FEE_DISTRIBUTOR_ADDRESS_INFO = keccak256(abi.encode(\"FEE_DISTRIBUTOR_ADDRESS_INFO\"));\n // @dev key for contract and keeper addresses stored by chain used in FeeDistributor\n bytes32 public constant FEE_DISTRIBUTOR_ADDRESS_INFO_FOR_CHAIN = keccak256(abi.encode(\"FEE_DISTRIBUTOR_ADDRESS_INFO_FOR_CHAIN\"));\n // @dev key for FeeDistributor keeper costs\n bytes32 public constant FEE_DISTRIBUTOR_KEEPER_COSTS = keccak256(abi.encode(\"FEE_DISTRIBUTOR_KEEPER_COSTS\"));\n // @dev key for FeeDistributor chainlink factor used to determine total chainlink fees paid\n bytes32 public constant FEE_DISTRIBUTOR_CHAINLINK_FACTOR = keccak256(abi.encode(\"FEE_DISTRIBUTOR_CHAINLINK_FACTOR\"));\n // @dev key for FeeDistributor total referral rewards deposited to the claim vault in a given week\n bytes32 public constant FEE_DISTRIBUTOR_REFERRAL_REWARDS_DEPOSITED = keccak256(abi.encode(\"FEE_DISTRIBUTOR_REFERRAL_REWARDS_DEPOSITED\"));\n // @dev key for max WNT amount from treasury to cover keeper costs\n bytes32 public constant FEE_DISTRIBUTOR_MAX_WNT_AMOUNT_FROM_TREASURY = keccak256(abi.encode(\"FEE_DISTRIBUTOR_MAX_WNT_AMOUNT_FROM_TREASURY\"));\n // @dev key for factor used to determine amount of total V1 fees USD that are in WNT\n bytes32 public constant FEE_DISTRIBUTOR_V1_FEES_WNT_FACTOR = keccak256(abi.encode(\"FEE_DISTRIBUTOR_V1_FEES_WNT_FACTOR\"));\n // @dev key for factor used to determine amount of total V2 fees USD that are in WNT\n bytes32 public constant FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR = keccak256(abi.encode(\"FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR\"));\n\n // @dev key for the multichain peers mapping (peer address stored as bytes32)\n // @param readChannel the readChannel for which to retrieve the respective peer\n // @return key for multichain peers\n function multichainPeersKey(uint32 readChannel) internal pure returns (bytes32) {\n return keccak256(abi.encode(MULTICHAIN_PEERS, readChannel));\n }\n\n // @dev key for the multichain number of confirmations\n // @param eid the endpoint id for which to retrieve the number of confirmations\n // @return key for multichain confirmations\n function multichainConfirmationsKey(uint32 eid) internal pure returns (bytes32) {\n return keccak256(abi.encode(MULTICHAIN_CONFIRMATIONS, eid));\n }\n\n // @dev key for the multichain guid to originator mapping\n // @param guid the guid for which to retrieve the originator address\n // @return key for multichain guid to originator\n function multichainGuidToOriginatorKey(bytes32 guid) internal pure returns (bytes32) {\n return keccak256(abi.encode(MULTICHAIN_GUID_TO_ORIGINATOR, guid));\n }\n\n // @dev key for the multichain authorized originators\n // @param originator the originator address to validate if authorized\n // @return key for multichain authorized originator\n function multichainAuthorizedOriginatorsKey(address originator) internal pure returns (bytes32) {\n return keccak256(abi.encode(MULTICHAIN_AUTHORIZED_ORIGINATORS, originator));\n }\n\n // @dev key for the FeeDistributor referral rewards amount\n // @param token the token the referral rewards are denominated in\n // @return key for FeeDistributor referral rewards amount\n function feeDistributorReferralRewardsAmountKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_REFERRAL_REWARDS_AMOUNT, token));\n }\n\n // @dev key for the FeeDistributor fee amount gmx\n // @param chainId the chainId for which to retrieve fee amount gmx\n // @return key for FeeDistributor fee amount gmx\n function feeDistributorFeeAmountGmxKey(uint256 chainId) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_FEE_AMOUNT_GMX, chainId));\n }\n\n // @dev key for the FeeDistributor fee amount in USD by version\n // @param version the version for which to retrieve the fee amount USD\n // @return key for FeeDistributor fee amount USD\n function feeDistributorFeeAmountUsdKey(uint256 version) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_FEE_AMOUNT_USD, version));\n }\n\n // @dev key for the FeeDistributor staked gmx\n // @param chainId the chainId for which to retrieve total staked\n // @return key for FeeDistributor staked gmx\n function feeDistributorStakedGmxKey(uint256 chainId) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_STAKED_GMX, chainId));\n }\n\n // @dev key for the FeeDistributor bridging slippage factor\n // @param chainId the chainId for which to retrieve max slippage\n // @return key for FeeDistributor bridging slippage factor\n function feeDistributorBridgeSlippageFactorKey(uint256 chainId) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_BRIDGE_SLIPPAGE_FACTOR, chainId));\n }\n\n // @dev key for FeeDistributor LayerZero version of chainId\n // @param chainId the chainId for the chain\n // @return key for FeeDistributor LayerZero chainId\n function feeDistributorLayerZeroChainIdKey(uint256 chainId) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_LAYERZERO_CHAIN_ID, chainId));\n }\n\n // @dev key for contract and keeper addresses used in FeeDistributor\n // @param addressName bytes32 representing the address to be retrieved\n // @return key for contract and keeper addresses used in FeeDistributor\n function feeDistributorAddressInfoKey(bytes32 addressName) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_ADDRESS_INFO, addressName));\n }\n\n // @dev key for contract and keeper addresses used in FeeDistributor stored by chain\n // @param chainId the chainId for the chain\n // @param addressName bytes32 representing the address to be retrieved\n // @return key for contract and keeper addresses used in FeeDistributor stored by chain\n function feeDistributorAddressInfoForChainKey(uint256 chainId, bytes32 addressName) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_ADDRESS_INFO_FOR_CHAIN, chainId, addressName));\n }\n\n // @dev key for FeeDistributor referral rewards deposited to the claim vault in a given week\n // @param token the token for which to check the referral rewards deposited\n // @return key for FeeDistributor referral rewards deposited in a given week\n function feeDistributorReferralRewardsDepositedKey(address token) internal pure returns (bytes32) {\n return keccak256(abi.encode(FEE_DISTRIBUTOR_REFERRAL_REWARDS_DEPOSITED, token));\n }\n}\n" + }, + "contracts/deposit/Deposit.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title Deposit\n// @dev Struct for deposits\nlibrary Deposit {\n enum DepositType {\n Normal,\n Shift,\n Glv\n }\n\n // @dev there is a limit on the number of fields a struct can have when being passed\n // or returned as a memory variable which can cause \"Stack too deep\" errors\n // use sub-structs to avoid this issue\n // @param addresses address values\n // @param numbers number values\n // @param flags boolean values\n // @param _dataList a list of bytes32 values that can be used for additional data\n struct Props {\n Addresses addresses;\n Numbers numbers;\n Flags flags;\n bytes32[] _dataList;\n }\n\n // @param account the account depositing liquidity\n // @param receiver the address to send the liquidity tokens to\n // @param callbackContract the callback contract\n // @param uiFeeReceiver the ui fee receiver\n // @param market the market to deposit to\n struct Addresses {\n address account;\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address initialLongToken;\n address initialShortToken;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n\n // @param initialLongTokenAmount the amount of long tokens to deposit\n // @param initialShortTokenAmount the amount of short tokens to deposit\n // @param minMarketTokens the minimum acceptable number of liquidity tokens\n // sending funds back to the user in case the deposit gets cancelled\n // @param executionFee the execution fee for keepers\n // @param callbackGasLimit the gas limit for the callbackContract\n // @param srcChainId the source chain id\n struct Numbers {\n uint256 initialLongTokenAmount;\n uint256 initialShortTokenAmount;\n uint256 minMarketTokens;\n uint256 updatedAtTime;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 srcChainId;\n }\n\n // @param shouldUnwrapNativeToken whether to unwrap the native token when\n struct Flags {\n bool shouldUnwrapNativeToken;\n }\n\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n function receiver(Props memory props) internal pure returns (address) {\n return props.addresses.receiver;\n }\n\n function setReceiver(Props memory props, address value) internal pure {\n props.addresses.receiver = value;\n }\n\n function callbackContract(Props memory props) internal pure returns (address) {\n return props.addresses.callbackContract;\n }\n\n function setCallbackContract(Props memory props, address value) internal pure {\n props.addresses.callbackContract = value;\n }\n\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.uiFeeReceiver;\n }\n\n function setUiFeeReceiver(Props memory props, address value) internal pure {\n props.addresses.uiFeeReceiver = value;\n }\n\n function market(Props memory props) internal pure returns (address) {\n return props.addresses.market;\n }\n\n function setMarket(Props memory props, address value) internal pure {\n props.addresses.market = value;\n }\n\n function initialLongToken(Props memory props) internal pure returns (address) {\n return props.addresses.initialLongToken;\n }\n\n function setInitialLongToken(Props memory props, address value) internal pure {\n props.addresses.initialLongToken = value;\n }\n\n function initialShortToken(Props memory props) internal pure returns (address) {\n return props.addresses.initialShortToken;\n }\n\n function setInitialShortToken(Props memory props, address value) internal pure {\n props.addresses.initialShortToken = value;\n }\n\n function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.longTokenSwapPath;\n }\n\n function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.longTokenSwapPath = value;\n }\n\n function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.shortTokenSwapPath;\n }\n\n function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.shortTokenSwapPath = value;\n }\n\n function initialLongTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.initialLongTokenAmount;\n }\n\n function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.initialLongTokenAmount = value;\n }\n\n function initialShortTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.initialShortTokenAmount;\n }\n\n function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.initialShortTokenAmount = value;\n }\n\n function minMarketTokens(Props memory props) internal pure returns (uint256) {\n return props.numbers.minMarketTokens;\n }\n\n function setMinMarketTokens(Props memory props, uint256 value) internal pure {\n props.numbers.minMarketTokens = value;\n }\n\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n\n function executionFee(Props memory props) internal pure returns (uint256) {\n return props.numbers.executionFee;\n }\n\n function setExecutionFee(Props memory props, uint256 value) internal pure {\n props.numbers.executionFee = value;\n }\n\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\n return props.numbers.callbackGasLimit;\n }\n\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\n props.numbers.callbackGasLimit = value;\n }\n\n function srcChainId(Props memory props) internal pure returns (uint256) {\n return props.numbers.srcChainId;\n }\n\n function setSrcChainId(Props memory props, uint256 value) internal pure {\n props.numbers.srcChainId = value;\n }\n\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\n return props.flags.shouldUnwrapNativeToken;\n }\n\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\n props.flags.shouldUnwrapNativeToken = value;\n }\n\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\n return props._dataList;\n }\n\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\n props._dataList = value;\n }\n}\n" + }, + "contracts/deposit/DepositEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nimport \"./Deposit.sol\";\nimport \"../pricing/ISwapPricingUtils.sol\";\n\nlibrary DepositEventUtils {\n using Deposit for Deposit.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitDepositCreated(\n EventEmitter eventEmitter,\n bytes32 key,\n Deposit.Props memory deposit,\n Deposit.DepositType depositType\n ) external {\n EventUtils.EventLogData memory eventData = createEventData(deposit, depositType);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog2(\n \"DepositCreated\",\n key,\n Cast.toBytes32(deposit.account()),\n eventData\n );\n }\n\n function emitDepositExecuted(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n uint256 longTokenAmount,\n uint256 shortTokenAmount,\n uint256 receivedMarketTokens,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(4);\n eventData.uintItems.setItem(0, \"longTokenAmount\", longTokenAmount);\n eventData.uintItems.setItem(1, \"shortTokenAmount\", shortTokenAmount);\n eventData.uintItems.setItem(2, \"receivedMarketTokens\", receivedMarketTokens);\n eventData.uintItems.setItem(3, \"swapPricingType\", uint256(swapPricingType));\n\n eventEmitter.emitEventLog2(\n \"DepositExecuted\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitDepositCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\n \"DepositCancelled\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function createEventData(Deposit.Props memory deposit, Deposit.DepositType depositType)\n public pure returns (EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(7);\n eventData.addressItems.setItem(0, \"account\", deposit.account());\n eventData.addressItems.setItem(1, \"receiver\", deposit.receiver());\n eventData.addressItems.setItem(2, \"callbackContract\", deposit.callbackContract());\n eventData.addressItems.setItem(3, \"market\", deposit.market());\n eventData.addressItems.setItem(4, \"initialLongToken\", deposit.initialLongToken());\n eventData.addressItems.setItem(5, \"initialShortToken\", deposit.initialShortToken());\n eventData.addressItems.setItem(6, \"uiFeeReceiver\", deposit.uiFeeReceiver());\n\n eventData.addressItems.initArrayItems(2);\n eventData.addressItems.setItem(0, \"longTokenSwapPath\", deposit.longTokenSwapPath());\n eventData.addressItems.setItem(1, \"shortTokenSwapPath\", deposit.shortTokenSwapPath());\n\n eventData.uintItems.initItems(8);\n eventData.uintItems.setItem(0, \"initialLongTokenAmount\", deposit.initialLongTokenAmount());\n eventData.uintItems.setItem(1, \"initialShortTokenAmount\", deposit.initialShortTokenAmount());\n eventData.uintItems.setItem(2, \"minMarketTokens\", deposit.minMarketTokens());\n eventData.uintItems.setItem(3, \"updatedAtTime\", deposit.updatedAtTime());\n eventData.uintItems.setItem(4, \"executionFee\", deposit.executionFee());\n eventData.uintItems.setItem(5, \"callbackGasLimit\", deposit.callbackGasLimit());\n eventData.uintItems.setItem(6, \"depositType\", uint256(depositType));\n eventData.uintItems.setItem(7, \"srcChainId\", deposit.srcChainId());\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"shouldUnwrapNativeToken\", deposit.shouldUnwrapNativeToken());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", deposit.dataList());\n return eventData;\n }\n}\n" + }, + "contracts/deposit/DepositStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Deposit.sol\";\n\n/**\n * @title DepositStoreUtils\n * @dev Library for deposit storage functions\n */\nlibrary DepositStoreUtils {\n using Deposit for Deposit.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant RECEIVER = keccak256(abi.encode(\"RECEIVER\"));\n bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode(\"CALLBACK_CONTRACT\"));\n bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode(\"UI_FEE_RECEIVER\"));\n bytes32 public constant MARKET = keccak256(abi.encode(\"MARKET\"));\n bytes32 public constant INITIAL_LONG_TOKEN = keccak256(abi.encode(\"INITIAL_LONG_TOKEN\"));\n bytes32 public constant INITIAL_SHORT_TOKEN = keccak256(abi.encode(\"INITIAL_SHORT_TOKEN\"));\n bytes32 public constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode(\"LONG_TOKEN_SWAP_PATH\"));\n bytes32 public constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode(\"SHORT_TOKEN_SWAP_PATH\"));\n\n bytes32 public constant INITIAL_LONG_TOKEN_AMOUNT = keccak256(abi.encode(\"INITIAL_LONG_TOKEN_AMOUNT\"));\n bytes32 public constant INITIAL_SHORT_TOKEN_AMOUNT = keccak256(abi.encode(\"INITIAL_SHORT_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_MARKET_TOKENS = keccak256(abi.encode(\"MIN_MARKET_TOKENS\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n bytes32 public constant EXECUTION_FEE = keccak256(abi.encode(\"EXECUTION_FEE\"));\n bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"CALLBACK_GAS_LIMIT\"));\n bytes32 public constant SRC_CHAIN_ID = keccak256(abi.encode(\"SRC_CHAIN_ID\"));\n\n bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode(\"SHOULD_UNWRAP_NATIVE_TOKEN\"));\n\n bytes32 public constant DATA_LIST = keccak256(abi.encode(\"DATA_LIST\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (Deposit.Props memory) {\n Deposit.Props memory deposit;\n if (!dataStore.containsBytes32(Keys.DEPOSIT_LIST, key)) {\n return deposit;\n }\n\n deposit.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n deposit.setReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, RECEIVER))\n ));\n\n deposit.setCallbackContract(dataStore.getAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n ));\n\n deposit.setUiFeeReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n ));\n\n deposit.setMarket(dataStore.getAddress(\n keccak256(abi.encode(key, MARKET))\n ));\n\n deposit.setInitialLongToken(dataStore.getAddress(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN))\n ));\n\n deposit.setInitialShortToken(dataStore.getAddress(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))\n ));\n\n deposit.setLongTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n ));\n\n deposit.setShortTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n ));\n\n deposit.setInitialLongTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))\n ));\n\n deposit.setInitialShortTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))\n ));\n\n deposit.setMinMarketTokens(dataStore.getUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS))\n ));\n\n deposit.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n deposit.setExecutionFee(dataStore.getUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n ));\n\n deposit.setCallbackGasLimit(dataStore.getUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n ));\n\n deposit.setSrcChainId(dataStore.getUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n ));\n\n deposit.setShouldUnwrapNativeToken(dataStore.getBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n ));\n\n deposit.setDataList(dataStore.getBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n ));\n\n return deposit;\n }\n\n function set(DataStore dataStore, bytes32 key, Deposit.Props memory deposit) external {\n dataStore.addBytes32(\n Keys.DEPOSIT_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountDepositListKey(deposit.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n deposit.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, RECEIVER)),\n deposit.receiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT)),\n deposit.callbackContract()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER)),\n deposit.uiFeeReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET)),\n deposit.market()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN)),\n deposit.initialLongToken()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)),\n deposit.initialShortToken()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),\n deposit.longTokenSwapPath()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),\n deposit.shortTokenSwapPath()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)),\n deposit.initialLongTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)),\n deposit.initialShortTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS)),\n deposit.minMarketTokens()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n deposit.updatedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, EXECUTION_FEE)),\n deposit.executionFee()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),\n deposit.callbackGasLimit()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID)),\n deposit.srcChainId()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),\n deposit.shouldUnwrapNativeToken()\n );\n\n dataStore.setBytes32Array(\n keccak256(abi.encode(key, DATA_LIST)),\n deposit.dataList()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.DEPOSIT_LIST, key)) {\n revert Errors.DepositNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.DEPOSIT_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountDepositListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n );\n\n dataStore.removeBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n );\n }\n\n function getDepositCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.DEPOSIT_LIST);\n }\n\n function getDepositKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.DEPOSIT_LIST, start, end);\n }\n\n function getAccountDepositCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountDepositListKey(account));\n }\n\n function getAccountDepositKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountDepositListKey(account), start, end);\n }\n}\n" + }, + "contracts/deposit/DepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"./DepositVault.sol\";\nimport \"./DepositStoreUtils.sol\";\nimport \"./DepositEventUtils.sol\";\nimport \"./IDepositUtils.sol\";\n\nimport \"../nonce/NonceUtils.sol\";\nimport \"../price/Price.sol\";\nimport \"../market/MarketUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\nimport \"../utils/AccountUtils.sol\";\nimport \"../multichain/MultichainUtils.sol\";\n\n// @title DepositUtils\n// @dev Library for deposit functions, to help with the depositing of liquidity\n// into a market in return for market tokens\nlibrary DepositUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n\n using Price for Price.Props;\n using Deposit for Deposit.Props;\n\n // @dev creates a deposit\n //\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param depositVault DepositVault\n // @param account the depositing account\n // @param srcChainId the source chain id\n // @param params CreateDepositParams\n function createDeposit(\n DataStore dataStore,\n EventEmitter eventEmitter,\n DepositVault depositVault,\n address account,\n uint256 srcChainId,\n IDepositUtils.CreateDepositParams memory params\n ) external returns (bytes32) {\n AccountUtils.validateAccount(account);\n\n Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, params.addresses.market);\n MarketUtils.validateSwapPath(dataStore, params.addresses.longTokenSwapPath);\n MarketUtils.validateSwapPath(dataStore, params.addresses.shortTokenSwapPath);\n\n // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would\n // be non-zero, the initialShortTokenAmount would be zero\n uint256 initialLongTokenAmount = depositVault.recordTransferIn(params.addresses.initialLongToken);\n uint256 initialShortTokenAmount = depositVault.recordTransferIn(params.addresses.initialShortToken);\n\n address wnt = TokenUtils.wnt(dataStore);\n\n if (params.addresses.initialLongToken == wnt) {\n initialLongTokenAmount -= params.executionFee;\n } else if (params.addresses.initialShortToken == wnt) {\n initialShortTokenAmount -= params.executionFee;\n } else {\n uint256 wntAmount = depositVault.recordTransferIn(wnt);\n if (wntAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);\n }\n\n params.executionFee = wntAmount;\n }\n\n if (initialLongTokenAmount == 0 && initialShortTokenAmount == 0) {\n revert Errors.EmptyDepositAmounts();\n }\n\n AccountUtils.validateReceiver(params.addresses.receiver);\n\n Deposit.Props memory deposit = Deposit.Props(\n Deposit.Addresses(\n account,\n params.addresses.receiver,\n params.addresses.callbackContract,\n params.addresses.uiFeeReceiver,\n market.marketToken,\n params.addresses.initialLongToken,\n params.addresses.initialShortToken,\n params.addresses.longTokenSwapPath,\n params.addresses.shortTokenSwapPath\n ),\n Deposit.Numbers(\n initialLongTokenAmount,\n initialShortTokenAmount,\n params.minMarketTokens,\n Chain.currentTimestamp(), // updatedAtTime\n params.executionFee,\n params.callbackGasLimit,\n srcChainId\n ),\n Deposit.Flags(\n params.shouldUnwrapNativeToken\n ),\n params.dataList\n );\n\n CallbackUtils.validateCallbackGasLimit(dataStore, deposit.callbackGasLimit());\n\n GasUtils.validateExecutionFee(\n dataStore,\n GasUtils.estimateExecuteDepositGasLimit(dataStore, deposit), // estimatedGasLimit\n params.executionFee,\n GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length) // oraclePriceCount\n );\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n\n DepositStoreUtils.set(dataStore, key, deposit);\n\n DepositEventUtils.emitDepositCreated(eventEmitter, key, deposit, Deposit.DepositType.Normal);\n\n return key;\n }\n\n // @dev cancels a deposit, funds are sent back to the user\n //\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param depositVault DepositVault\n // @param key the key of the deposit to cancel\n // @param keeper the address of the keeper\n // @param startingGas the starting gas amount\n function cancelDeposit(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n DepositVault depositVault,\n bytes32 key,\n address keeper,\n uint256 startingGas,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n startingGas -= gasleft() / 63;\n\n Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);\n if (deposit.account() == address(0)) {\n revert Errors.EmptyDeposit();\n }\n\n if (\n deposit.initialLongTokenAmount() == 0 &&\n deposit.initialShortTokenAmount() == 0\n ) {\n revert Errors.EmptyDepositAmounts();\n }\n\n DepositStoreUtils.remove(dataStore, key, deposit.account());\n\n if (deposit.initialLongTokenAmount() > 0) {\n if (deposit.srcChainId() == 0) {\n depositVault.transferOut(\n deposit.initialLongToken(),\n deposit.account(),\n deposit.initialLongTokenAmount(),\n deposit.shouldUnwrapNativeToken()\n );\n } else {\n depositVault.transferOut(\n deposit.initialLongToken(),\n address(multichainVault),\n deposit.initialLongTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n deposit.initialLongToken(),\n deposit.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n }\n\n if (deposit.initialShortTokenAmount() > 0) {\n if (deposit.srcChainId() == 0) {\n depositVault.transferOut(\n deposit.initialShortToken(),\n deposit.account(),\n deposit.initialShortTokenAmount(),\n deposit.shouldUnwrapNativeToken()\n );\n } else {\n depositVault.transferOut(\n deposit.initialShortToken(),\n address(multichainVault),\n deposit.initialShortTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n deposit.initialShortToken(),\n deposit.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n }\n\n DepositEventUtils.emitDepositCancelled(\n eventEmitter,\n key,\n deposit.account(),\n reason,\n reasonBytes\n );\n\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterDepositCancellation(key, deposit, eventData);\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n dataStore,\n eventEmitter,\n multichainVault,\n depositVault\n ),\n key,\n deposit.callbackContract(),\n deposit.executionFee(),\n startingGas,\n GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length),\n keeper,\n deposit.receiver(),\n deposit.srcChainId()\n );\n }\n}\n" + }, + "contracts/deposit/DepositVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/StrictBank.sol\";\n\n// @title DepositVault\n// @dev Vault for deposits\ncontract DepositVault is StrictBank {\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\n}\n" + }, + "contracts/deposit/ExecuteDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"./IExecuteDepositUtils.sol\";\nimport \"./DepositVault.sol\";\nimport \"./DepositStoreUtils.sol\";\nimport \"./DepositEventUtils.sol\";\n\nimport \"../pricing/SwapPricingUtils.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../position/PositionUtils.sol\";\nimport \"../swap/ISwapUtils.sol\";\nimport \"../fee/FeeUtils.sol\";\n\nimport \"../multichain/MultichainUtils.sol\";\nimport \"../multichain/BridgeOutFromControllerUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\n\nimport \"../utils/Array.sol\";\n\n// @title DepositUtils\n// @dev Library for deposit functions, to help with the depositing of liquidity\n// into a market in return for market tokens\nlibrary ExecuteDepositUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n using Array for uint256[];\n\n using Price for Price.Props;\n using Deposit for Deposit.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n struct _ExecuteDepositParams {\n Market.Props market;\n address account;\n address receiver;\n address uiFeeReceiver;\n address tokenIn;\n address tokenOut;\n Price.Props tokenInPrice;\n Price.Props tokenOutPrice;\n uint256 amount;\n int256 priceImpactUsd;\n uint256 srcChainId;\n }\n\n struct ExecuteDepositCache {\n uint256 requestExpirationTime;\n uint256 maxOracleTimestamp;\n Market.Props market;\n MarketUtils.MarketPrices prices;\n uint256 longTokenAmount;\n uint256 shortTokenAmount;\n uint256 longTokenUsd;\n uint256 shortTokenUsd;\n uint256 receivedMarketTokens;\n int256 priceImpactUsd;\n bool balanceWasImproved;\n uint256 marketTokensSupply;\n EventUtils.EventLogData callbackEventData;\n }\n\n address public constant RECEIVER_FOR_FIRST_DEPOSIT = address(1);\n\n // @dev executes a deposit\n // @param params ExecuteDepositParams\n function executeDeposit(IExecuteDepositUtils.ExecuteDepositParams memory params, Deposit.Props memory deposit) external returns (uint256 receivedMarketTokens) {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n DepositStoreUtils.remove(params.dataStore, params.key, deposit.account());\n\n\n if (deposit.account() == address(0)) {\n revert Errors.EmptyDeposit();\n }\n\n if (params.oracle.minTimestamp() < deposit.updatedAtTime()) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(\n params.oracle.minTimestamp(),\n deposit.updatedAtTime()\n );\n }\n\n ExecuteDepositCache memory cache;\n cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);\n cache.maxOracleTimestamp = params.oracle.maxTimestamp();\n\n if (cache.maxOracleTimestamp > deposit.updatedAtTime() + cache.requestExpirationTime) {\n revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(\n cache.maxOracleTimestamp,\n deposit.updatedAtTime(),\n cache.requestExpirationTime\n );\n }\n\n cache.market = MarketUtils.getEnabledMarket(params.dataStore, deposit.market());\n\n _validateFirstDeposit(params, deposit, cache.market);\n\n cache.prices = MarketUtils.getMarketPrices(params.oracle, cache.market);\n\n MarketUtils.distributePositionImpactPool(\n params.dataStore,\n params.eventEmitter,\n cache.market.marketToken\n );\n\n PositionUtils.updateFundingAndBorrowingState(\n params.dataStore,\n params.eventEmitter,\n cache.market,\n cache.prices\n );\n\n // deposits should improve the pool state but it should be checked if\n // the max pnl factor for deposits is exceeded as this would lead to the\n // price of the market token decreasing below a target minimum percentage\n // due to pnl\n // note that this is just a validation for deposits, there is no actual\n // minimum price for a market token\n MarketUtils.validateMaxPnl(\n params.dataStore,\n cache.market,\n cache.prices,\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS\n );\n\n cache.longTokenAmount = swap(\n params,\n deposit.longTokenSwapPath(),\n deposit.initialLongToken(),\n deposit.initialLongTokenAmount(),\n cache.market.marketToken,\n cache.market.longToken,\n deposit.uiFeeReceiver()\n );\n\n cache.shortTokenAmount = swap(\n params,\n deposit.shortTokenSwapPath(),\n deposit.initialShortToken(),\n deposit.initialShortTokenAmount(),\n cache.market.marketToken,\n cache.market.shortToken,\n deposit.uiFeeReceiver()\n );\n\n if (cache.longTokenAmount == 0 && cache.shortTokenAmount == 0) {\n revert Errors.EmptyDepositAmountsAfterSwap();\n }\n\n cache.longTokenUsd = cache.longTokenAmount * cache.prices.longTokenPrice.midPrice();\n cache.shortTokenUsd = cache.shortTokenAmount * cache.prices.shortTokenPrice.midPrice();\n\n (cache.priceImpactUsd, cache.balanceWasImproved) = SwapPricingUtils.getPriceImpactUsd(\n SwapPricingUtils.GetPriceImpactUsdParams(\n params.dataStore,\n cache.market,\n cache.market.longToken,\n cache.market.shortToken,\n cache.prices.longTokenPrice.midPrice(),\n cache.prices.shortTokenPrice.midPrice(),\n cache.longTokenUsd.toInt256(),\n cache.shortTokenUsd.toInt256(),\n params.includeVirtualInventoryImpact\n )\n );\n\n if (cache.longTokenAmount > 0) {\n _ExecuteDepositParams memory _params = _ExecuteDepositParams(\n cache.market,\n deposit.account(),\n deposit.receiver(),\n deposit.uiFeeReceiver(),\n cache.market.longToken,\n cache.market.shortToken,\n cache.prices.longTokenPrice,\n cache.prices.shortTokenPrice,\n cache.longTokenAmount,\n Precision.mulDiv(cache.priceImpactUsd, cache.longTokenUsd, cache.longTokenUsd + cache.shortTokenUsd),\n deposit.srcChainId()\n );\n\n cache.receivedMarketTokens += _executeDeposit(params, _params, cache.balanceWasImproved);\n }\n\n if (cache.shortTokenAmount > 0) {\n _ExecuteDepositParams memory _params = _ExecuteDepositParams(\n cache.market,\n deposit.account(),\n deposit.receiver(),\n deposit.uiFeeReceiver(),\n cache.market.shortToken,\n cache.market.longToken,\n cache.prices.shortTokenPrice,\n cache.prices.longTokenPrice,\n cache.shortTokenAmount,\n Precision.mulDiv(cache.priceImpactUsd, cache.shortTokenUsd, cache.longTokenUsd + cache.shortTokenUsd),\n deposit.srcChainId()\n );\n\n cache.receivedMarketTokens += _executeDeposit(params, _params, cache.balanceWasImproved);\n }\n\n if (cache.receivedMarketTokens < deposit.minMarketTokens()) {\n revert Errors.MinMarketTokens(cache.receivedMarketTokens, deposit.minMarketTokens());\n }\n\n // validate that internal state changes are correct before calling\n // external callbacks\n MarketUtils.validateMarketTokenBalance(params.dataStore, cache.market);\n\n DepositEventUtils.emitDepositExecuted(\n params.eventEmitter,\n params.key,\n deposit.account(),\n cache.longTokenAmount,\n cache.shortTokenAmount,\n cache.receivedMarketTokens,\n params.swapPricingType\n );\n\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n cache.market,\n cache.prices.indexTokenPrice,\n cache.prices.longTokenPrice,\n cache.prices.shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n true\n );\n\n cache.marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(cache.market.marketToken)));\n\n MarketEventUtils.emitMarketPoolValueUpdated(\n params.eventEmitter,\n keccak256(abi.encode(\"DEPOSIT\")),\n params.key,\n cache.market.marketToken,\n poolValueInfo,\n cache.marketTokensSupply\n );\n\n cache.callbackEventData.uintItems.initItems(1);\n cache.callbackEventData.uintItems.setItem(0, \"receivedMarketTokens\", cache.receivedMarketTokens);\n CallbackUtils.afterDepositExecution(params.key, deposit, cache.callbackEventData);\n\n // use deposit.dataList to determine if the GM tokens minted should be bridged out to src chain\n BridgeOutFromControllerUtils.bridgeOutFromController(\n params.eventEmitter,\n params.multichainTransferRouter,\n deposit.account(),\n deposit.receiver(),\n deposit.srcChainId(),\n cache.market.marketToken, // token\n cache.receivedMarketTokens, // amount\n deposit.dataList()\n );\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.depositVault\n ),\n params.key,\n deposit.callbackContract(),\n deposit.executionFee(),\n params.startingGas,\n GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length),\n params.keeper,\n deposit.receiver(),\n deposit.srcChainId()\n );\n\n return cache.receivedMarketTokens;\n }\n\n // @dev executes a deposit\n // @param params ExecuteDepositParams\n // @param _params _ExecuteDepositParams\n function _executeDeposit(\n IExecuteDepositUtils.ExecuteDepositParams memory params,\n _ExecuteDepositParams memory _params,\n bool balanceWasImproved\n ) internal returns (uint256) {\n // for markets where longToken == shortToken, the price impact factor should be set to zero\n // in which case, the priceImpactUsd would always equal zero\n SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(\n params.dataStore,\n _params.market.marketToken,\n _params.amount,\n balanceWasImproved,\n _params.uiFeeReceiver,\n params.swapPricingType\n );\n\n FeeUtils.incrementClaimableFeeAmount(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n _params.tokenIn,\n fees.feeReceiverAmount,\n Keys.DEPOSIT_FEE_TYPE\n );\n\n FeeUtils.incrementClaimableUiFeeAmount(\n params.dataStore,\n params.eventEmitter,\n _params.uiFeeReceiver,\n _params.market.marketToken,\n _params.tokenIn,\n fees.uiFeeAmount,\n Keys.UI_DEPOSIT_FEE_TYPE\n );\n\n SwapPricingUtils.emitSwapFeesCollected(\n params.eventEmitter,\n params.key,\n _params.market.marketToken,\n _params.tokenIn,\n _params.tokenInPrice.min,\n Keys.DEPOSIT_FEE_TYPE,\n fees\n );\n\n uint256 mintAmount;\n\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n _params.market,\n params.oracle.getPrimaryPrice(_params.market.indexToken),\n _params.tokenIn == _params.market.longToken ? _params.tokenInPrice : _params.tokenOutPrice,\n _params.tokenIn == _params.market.shortToken ? _params.tokenInPrice : _params.tokenOutPrice,\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n true\n );\n\n if (poolValueInfo.poolValue < 0) {\n revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);\n }\n\n uint256 poolValue = poolValueInfo.poolValue.toUint256();\n\n uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(_params.market.marketToken)));\n\n if (poolValueInfo.poolValue == 0 && marketTokensSupply > 0) {\n revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);\n }\n\n MarketEventUtils.emitMarketPoolValueInfo(\n params.eventEmitter,\n params.key,\n _params.market.marketToken,\n poolValueInfo,\n marketTokensSupply\n );\n\n // the poolValue and marketTokensSupply is cached for the mintAmount calculation below\n // so the effect of any positive price impact on the poolValue and marketTokensSupply\n // would not be accounted for\n //\n // for most cases, this should not be an issue, since the poolValue and marketTokensSupply\n // should have been proportionately increased\n //\n // e.g. if the poolValue is $100 and marketTokensSupply is 100, and there is a positive price impact\n // of $10, the poolValue should have increased by $10 and the marketTokensSupply should have been increased by 10\n //\n // there is a case where this may be an issue which is when all tokens are withdrawn from an existing market\n // and the marketTokensSupply is reset to zero, but the poolValue is not entirely zero\n // the case where this happens should be very rare and during withdrawal the poolValue should be close to zero\n //\n // however, in case this occurs, the usdToMarketTokenAmount will mint an additional number of market tokens\n // proportional to the existing poolValue\n //\n // since the poolValue and marketTokensSupply is cached, this could occur once during positive price impact\n // and again when calculating the mintAmount\n //\n // to avoid this, set the priceImpactUsd to be zero for this case\n if (_params.priceImpactUsd > 0 && marketTokensSupply == 0) {\n _params.priceImpactUsd = 0;\n }\n\n if (_params.priceImpactUsd > 0) {\n // when there is a positive price impact factor,\n // tokens from the swap impact pool are used to mint additional market tokens for the user\n // for example, if 50,000 USDC is deposited and there is a positive price impact\n // an additional 0.005 ETH may be used to mint market tokens\n // the swap impact pool is decreased by the used amount\n //\n // priceImpactUsd is calculated based on pricing assuming only depositAmount of tokenIn\n // was added to the pool\n // since impactAmount of tokenOut is added to the pool here, the calculation of\n // the price impact would not be entirely accurate\n //\n // it is possible that the addition of the positive impact amount of tokens into the pool\n // could increase the imbalance of the pool, for most cases this should not be a significant\n // change compared to the improvement of balance from the actual deposit\n (int256 positiveImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n _params.tokenOut,\n _params.tokenOutPrice,\n _params.priceImpactUsd\n );\n\n // calculate the usd amount using positiveImpactAmount since it may\n // be capped by the max available amount in the impact pool\n // use tokenOutPrice.max to get the USD value since the positiveImpactAmount\n // was calculated using a USD value divided by tokenOutPrice.max\n //\n // for the initial deposit, the pool value and token supply would be zero\n // so the market token price is treated as 1 USD\n //\n // it is possible for the pool value to be more than zero and the token supply\n // to be zero, in that case, the market token price is also treated as 1 USD\n mintAmount += MarketUtils.usdToMarketTokenAmount(\n positiveImpactAmount.toUint256() * _params.tokenOutPrice.max,\n poolValue,\n marketTokensSupply\n );\n\n // deposit the token out, that was withdrawn from the impact pool, to mint market tokens\n MarketUtils.applyDeltaToPoolAmount(\n params.dataStore,\n params.eventEmitter,\n _params.market,\n _params.tokenOut,\n positiveImpactAmount\n );\n\n // MarketUtils.validatePoolUsdForDeposit is not called here\n // this is to prevent unnecessary reverts\n // for example, if the pool's long token is close to the deposit cap\n // but the short token is not close to the cap, depositing the short\n // token can lead to a positive price impact which can cause the\n // long token's deposit cap to be exceeded\n // in this case, it is preferrable that the pool can still be\n // rebalanced even if the deposit cap may be exceeded\n\n MarketUtils.validatePoolAmount(\n params.dataStore,\n _params.market,\n _params.tokenOut\n );\n }\n\n if (_params.priceImpactUsd < 0) {\n // when there is a negative price impact factor,\n // less of the deposit amount is used to mint market tokens\n // for example, if 10 ETH is deposited and there is a negative price impact\n // only 9.995 ETH may be used to mint market tokens\n // the remaining 0.005 ETH will be stored in the swap impact pool\n (int256 negativeImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n _params.tokenIn,\n _params.tokenInPrice,\n _params.priceImpactUsd\n );\n\n fees.amountAfterFees -= (-negativeImpactAmount).toUint256();\n }\n\n mintAmount += MarketUtils.usdToMarketTokenAmount(\n fees.amountAfterFees * _params.tokenInPrice.min,\n poolValue,\n marketTokensSupply\n );\n\n MarketUtils.applyDeltaToPoolAmount(\n params.dataStore,\n params.eventEmitter,\n _params.market,\n _params.tokenIn,\n (fees.amountAfterFees + fees.feeAmountForPool).toInt256()\n );\n\n MarketUtils.validatePoolUsdForDeposit(\n params.dataStore,\n _params.market,\n _params.tokenIn,\n _params.tokenInPrice.max\n );\n\n MarketUtils.validatePoolAmount(\n params.dataStore,\n _params.market,\n _params.tokenIn\n );\n\n if (_params.srcChainId == 0) {\n // mint GM tokens to receiver\n MarketToken(payable(_params.market.marketToken)).mint(_params.receiver, mintAmount);\n } else {\n // mint GM tokens to MultichainVault and increase receiver's multichain GM balance\n MarketToken(payable(_params.market.marketToken)).mint(address(params.multichainVault), mintAmount);\n MultichainUtils.recordTransferIn(params.dataStore, params.eventEmitter, params.multichainVault, _params.market.marketToken, _params.receiver, 0); // srcChainId is the current block.chainId\n }\n\n return mintAmount;\n }\n\n function swap(\n IExecuteDepositUtils.ExecuteDepositParams memory params,\n address[] memory swapPath,\n address initialToken,\n uint256 inputAmount,\n address market,\n address expectedOutputToken,\n address uiFeeReceiver\n ) internal returns (uint256) {\n Market.Props[] memory swapPathMarkets = MarketUtils.getSwapPathMarkets(\n params.dataStore,\n swapPath\n );\n\n (address outputToken, uint256 outputAmount) = params.swapHandler.swap(\n ISwapUtils.SwapParams(\n params.dataStore, // dataStore\n params.eventEmitter, // eventEmitter\n params.oracle, // oracle\n params.depositVault, // bank\n params.key, // key\n initialToken, // tokenIn\n inputAmount, // amountIn\n swapPathMarkets, // swapPathMarkets\n 0, // minOutputAmount\n market, // receiver\n uiFeeReceiver, // uiFeeReceiver\n false, // shouldUnwrapNativeToken\n ISwapPricingUtils.SwapPricingType.Swap\n )\n );\n\n if (outputToken != expectedOutputToken) {\n revert Errors.InvalidSwapOutputToken(outputToken, expectedOutputToken);\n }\n\n MarketUtils.validateMarketTokenBalance(params.dataStore, swapPathMarkets);\n\n return outputAmount;\n }\n\n // this method validates that a specified minimum number of market tokens are locked\n // this can be used to help ensure a minimum amount of liquidity for a market\n // this also helps to prevent manipulation of the market token price by the first depositor\n // since it may be possible to deposit a small amount of tokens on the first deposit\n // to cause a high market token price due to rounding of the amount of tokens minted\n function _validateFirstDeposit(\n IExecuteDepositUtils.ExecuteDepositParams memory params,\n Deposit.Props memory deposit,\n Market.Props memory market\n ) internal view {\n uint256 initialMarketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));\n\n // return if this is not the first deposit\n if (initialMarketTokensSupply != 0) { return; }\n\n uint256 minMarketTokens = params.dataStore.getUint(Keys.minMarketTokensForFirstDepositKey(market.marketToken));\n\n // return if there is no minMarketTokens requirement\n if (minMarketTokens == 0) { return; }\n\n if (deposit.receiver() != RECEIVER_FOR_FIRST_DEPOSIT) {\n revert Errors.InvalidReceiverForFirstDeposit(deposit.receiver(), RECEIVER_FOR_FIRST_DEPOSIT);\n }\n\n if (deposit.minMarketTokens() < minMarketTokens) {\n revert Errors.InvalidMinMarketTokensForFirstDeposit(deposit.minMarketTokens(), minMarketTokens);\n }\n }\n}\n" + }, + "contracts/deposit/IDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IDepositUtils {\n // @dev CreateDepositParams struct used in createDeposit to avoid stack\n // too deep errors\n //\n // @param receiver the address to send the market tokens to\n // @param callbackContract the callback contract\n // @param uiFeeReceiver the ui fee receiver\n // @param market the market to deposit into\n // @param minMarketTokens the minimum acceptable number of liquidity tokens\n // @param shouldUnwrapNativeToken whether to unwrap the native token when\n // sending funds back to the user in case the deposit gets cancelled\n // @param executionFee the execution fee for keepers\n // @param callbackGasLimit the gas limit for the callbackContract\n // @param dataList a list of bytes32 values that can be used for additional data\n struct CreateDepositParams {\n CreateDepositParamsAddresses addresses;\n uint256 minMarketTokens;\n bool shouldUnwrapNativeToken;\n uint256 executionFee;\n uint256 callbackGasLimit;\n bytes32[] dataList;\n }\n\n struct CreateDepositParamsAddresses {\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address initialLongToken;\n address initialShortToken;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n}\n" + }, + "contracts/deposit/IExecuteDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../multichain/MultichainVault.sol\";\nimport \"../multichain/IMultichainTransferRouter.sol\";\nimport \"../deposit/DepositVault.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../pricing/ISwapPricingUtils.sol\";\nimport \"../swap/ISwapHandler.sol\";\n\ninterface IExecuteDepositUtils {\n // @dev ExecuteDepositParams struct used in executeDeposit to avoid stack\n // too deep errors\n struct ExecuteDepositParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n IMultichainTransferRouter multichainTransferRouter;\n DepositVault depositVault;\n IOracle oracle;\n ISwapHandler swapHandler;\n bytes32 key;\n address keeper;\n uint256 startingGas;\n ISwapPricingUtils.SwapPricingType swapPricingType;\n bool includeVirtualInventoryImpact;\n }\n}\n" + }, + "contracts/error/Errors.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nlibrary Errors {\n // AdlHandler errors\n error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);\n error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);\n error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);\n\n // AdlUtils errors\n error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\n error AdlNotEnabled();\n\n // AutoCancelUtils errors\n error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);\n\n // Bank errors\n error SelfTransferNotSupported(address receiver);\n error InvalidNativeTokenSender(address msgSender);\n\n // BaseHandler errors\n error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);\n\n // CallbackUtils errors\n error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);\n error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);\n\n // Config errors\n error InvalidBaseKey(bytes32 baseKey);\n error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);\n error InvalidClaimableFactor(uint256 value);\n error InvalidClaimableReductionFactor(uint256 value);\n error OracleProviderAlreadyExistsForToken(address oracle, address token);\n error OracleProviderMinChangeDelayNotYetPassed(address token, address provider);\n error PriceFeedAlreadyExistsForToken(address token);\n error DataStreamIdAlreadyExistsForToken(address token);\n error EdgeDataStreamIdAlreadyExistsForToken(address token);\n error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);\n error InvalidPositionImpactPoolDistributionRate(uint256 distributionAmount, uint256 positionImpactPoolAmount);\n error MaxDataListLengthExceeded(uint256 dataLength, uint256 maxDataLength);\n error EmptyToken();\n\n // ContributorHandler errors\n error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);\n error InvalidContributorToken(address token);\n error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);\n error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);\n error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);\n error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);\n\n // Timelock errors\n error ActionAlreadySignalled();\n error ActionNotSignalled();\n error SignalTimeNotYetPassed(uint256 signalTime);\n error InvalidTimelockDelay(uint256 timelockDelay);\n error MaxTimelockDelayExceeded(uint256 timelockDelay);\n error InvalidFeeReceiver(address receiver);\n error InvalidOracleSigner(address signer);\n error InvalidHoldingAddress(address account);\n error EmptyPositionImpactWithdrawalAmount();\n error OraclePriceOutdated();\n error EmptyTarget();\n error EmptyFundingAccount();\n error EmptyReduceLentAmount();\n error ReductionExceedsLentAmount(uint256 lentAmount, uint256 totalReductionAmount);\n\n // GlvDepositStoreUtils errors\n error GlvDepositNotFound(bytes32 key);\n // GlvShiftStoreUtils errors\n error GlvShiftNotFound(bytes32 key);\n // GlvWithdrawalStoreUtils errors\n error GlvWithdrawalNotFound(bytes32 key);\n // GlvDepositUtils errors\n error EmptyGlvDepositAmounts();\n error EmptyGlvMarketAmount();\n error EmptyGlvDeposit();\n error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);\n error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);\n // GlvWithdrawalUtils errors\n error EmptyGlvWithdrawal();\n error EmptyGlvWithdrawalAmount();\n // GlvUtils errors\n error EmptyGlv(address glv);\n error EmptyGlvTokenSupply();\n error GlvNegativeMarketPoolValue(address glv, address market);\n error GlvUnsupportedMarket(address glv, address market);\n error GlvDisabledMarket(address glv, address market);\n error GlvEnabledMarket(address glv, address market);\n error GlvNonZeroMarketBalance(address glv, address market);\n error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);\n error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);\n error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);\n error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);\n error GlvMarketAlreadyExists(address glv, address market);\n error GlvInvalidLongToken(address glv, address provided, address expected);\n error GlvInvalidShortToken(address glv, address provided, address expected);\n // GlvShiftUtils\n error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);\n error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);\n // GlvFactory\n error GlvAlreadyExists(bytes32 salt, address glv);\n error GlvSymbolTooLong();\n error GlvNameTooLong();\n // GlvStoreUtils\n error GlvNotFound(address key);\n\n // DepositStoreUtils errors\n error DepositNotFound(bytes32 key);\n\n // DepositUtils errors\n error EmptyDeposit();\n error EmptyDepositAmounts();\n\n // ExecuteDepositUtils errors\n error MinMarketTokens(uint256 received, uint256 expected);\n error EmptyDepositAmountsAfterSwap();\n error InvalidPoolValueForDeposit(int256 poolValue);\n error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);\n error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);\n error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);\n\n // ExternalHandler errors\n error ExternalCallFailed(bytes data);\n error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);\n error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);\n error InvalidExternalCallTarget(address target);\n\n // FeeBatchStoreUtils errors\n error FeeBatchNotFound(bytes32 key);\n\n // FeeDistributor errors\n error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);\n error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);\n error InvalidSwapPathForV1(address[] path, address bridgingToken);\n\n // GlpMigrator errors\n error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);\n error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);\n\n // GlvHandler errors\n error InvalidGlvDepositInitialLongToken(address initialLongToken);\n error InvalidGlvDepositInitialShortToken(address initialShortToken);\n error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\n error MinGlvTokens(uint256 received, uint256 expected);\n\n // OrderHandler errors\n error OrderNotUpdatable(uint256 orderType);\n error InvalidKeeperForFrozenOrder(address keeper);\n\n // FeatureUtils errors\n error DisabledFeature(bytes32 key);\n\n // FeeHandler errors\n error InvalidBuybackToken(address buybackToken);\n error InvalidVersion(uint256 version);\n error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);\n error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);\n error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);\n error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);\n error EmptyClaimFeesMarket();\n\n // GasUtils errors\n error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);\n error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);\n error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);\n error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);\n error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);\n error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\n error InsufficientGasForAutoCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);\n error InsufficientGasLeft(uint256 gas, uint256 estimatedGasLimit);\n error InvalidExecutionFee(uint256 executionFee, uint256 minExecutionFee, uint256 maxExecutionFee);\n error EmptyRelayFeeAddress();\n\n // MarketFactory errors\n error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);\n\n // MarketStoreUtils errors\n error MarketNotFound(address key);\n\n // MarketUtils errors\n error EmptyMarket();\n error DisabledMarket(address market);\n error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);\n error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);\n error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);\n error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);\n error UnableToGetOppositeToken(address inputToken, address market);\n error UnexpectedTokenForVirtualInventory(address token, address market);\n error EmptyMarketTokenSupply();\n error InvalidSwapMarket(address market);\n error UnableToGetCachedTokenPrice(address token, address market);\n error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);\n error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);\n error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);\n error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);\n error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);\n error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);\n error UnableToGetBorrowingFactorEmptyPoolUsd();\n error UnableToGetFundingFactorEmptyOpenInterest();\n error InvalidPositionMarket(address market);\n error InvalidCollateralTokenForMarket(address market, address token);\n error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);\n error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);\n error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);\n error EmptyAddressInMarketTokenBalanceValidation(address market, address token);\n error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);\n error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);\n error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);\n error UnexpectedPoolValue(int256 poolValue);\n\n // MarketPositionImpactUtils errors\n error InsufficientImpactPoolValueForWithdrawal(uint256 withdrawalAmount, uint256 poolValue, int256 totalPendingImpactAmount);\n\n // Oracle errors\n error SequencerDown();\n error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);\n error EmptyValidatedPrices(); // not used, kept for compatibility\n error InvalidOracleProvider(address provider);\n error InvalidOracleProviderForToken(address provider, address expectedProvider);\n error GmEmptySigner(uint256 signerIndex);\n error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);\n error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);\n error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);\n error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);\n error EmptyDataStreamFeedId(address token);\n error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);\n error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);\n error InvalidDataStreamPrices(address token, int192 bid, int192 ask);\n error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);\n error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);\n error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);\n error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);\n error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);\n error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);\n error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);\n error EmptyChainlinkPriceFeedMultiplier(address token);\n error EmptyDataStreamMultiplier(address token);\n error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);\n error InvalidFeedPrice(address token, int256 price);\n error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);\n error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);\n error InvalidGmOraclePrice(address token);\n error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);\n error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);\n error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);\n error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);\n error EmptyChainlinkPriceFeed(address token);\n error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);\n error MaxRefPriceDeviationExceeded(\n address token,\n uint256 price,\n uint256 refPrice,\n uint256 maxRefPriceDeviationFactor\n );\n error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);\n error NonAtomicOracleProvider(address provider);\n\n // OracleModule errors\n error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);\n error EndOfOracleSimulation();\n\n // OracleUtils errors\n error InvalidGmSignature(address recoveredSigner, address expectedSigner);\n\n error EmptyPrimaryPrice(address token);\n\n error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);\n error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);\n\n // BaseOrderUtils errors\n error EmptyOrder();\n error UnsupportedOrderType(uint256 orderType);\n error UnsupportedOrderTypeForAutoCancellation(uint256 orderType);\n error InvalidOrderPrices(\n uint256 primaryPriceMin,\n uint256 primaryPriceMax,\n uint256 triggerPrice,\n uint256 orderType\n );\n error EmptySizeDeltaInTokens();\n error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);\n error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);\n error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);\n error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);\n\n // IncreaseOrderUtils errors\n error UnexpectedPositionState();\n\n // OrderUtils errors\n error OrderTypeCannotBeCreated(uint256 orderType);\n error OrderAlreadyFrozen();\n error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);\n error InvalidReceiver(address receiver);\n error UnexpectedValidFromTime(uint256 orderType);\n\n // OrderStoreUtils errors\n error OrderNotFound(bytes32 key);\n\n // SwapOrderUtils errors\n error UnexpectedMarket();\n\n // DecreasePositionCollateralUtils errors\n error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);\n error InvalidOutputToken(address tokenOut, address expectedTokenOut);\n\n // DecreasePositionUtils errors\n error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);\n error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);\n error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);\n error PositionShouldNotBeLiquidated(\n string reason,\n int256 remainingCollateralUsd,\n int256 minCollateralUsd,\n int256 minCollateralUsdForLeverage\n );\n\n // IncreasePositionUtils errors\n error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);\n error InsufficientCollateralUsd(int256 remainingCollateralUsd);\n\n // PositionStoreUtils errors\n error PositionNotFound(bytes32 key);\n\n // PositionUtils errors\n error LiquidatablePosition(\n string reason,\n int256 remainingCollateralUsd,\n int256 minCollateralUsd,\n int256 minCollateralUsdForLeverage\n );\n\n error EmptyPosition();\n error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);\n error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);\n\n // PositionPricingUtils errors\n error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);\n error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);\n\n // ShiftStoreUtils errors\n error ShiftNotFound(bytes32 key);\n\n // ShiftUtils errors\n error EmptyShift();\n error EmptyShiftAmount();\n error ShiftFromAndToMarketAreEqual(address market);\n error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\n error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);\n error BridgeOutNotSupportedDuringShift();\n\n // SwapPricingUtils errors\n error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);\n\n // RoleModule errors\n error Unauthorized(address msgSender, string role);\n\n // RoleStore errors\n error ThereMustBeAtLeastOneRoleAdmin();\n error ThereMustBeAtLeastOneTimelockMultiSig();\n\n // ExchangeRouter errors\n error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);\n error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);\n error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);\n error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);\n\n // SwapUtils errors\n error InvalidTokenIn(address tokenIn, address market);\n error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\n error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);\n error DuplicatedMarketInSwapPath(address market);\n error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);\n\n // SubaccountRouter errors\n error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);\n error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);\n\n // SubaccountUtils errors\n error SubaccountNotAuthorized(address account, address subaccount);\n error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);\n error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);\n error SubaccountIntegrationIdDisabled(bytes32 integrationId);\n\n // TokenUtils errors\n error TokenTransferError(address token, address receiver, uint256 amount);\n error EmptyHoldingAddress();\n // Note that Transfer is misspelled as Tranfer in the EmptyTokenTranferGasLimit error\n // some contracts with this error cannot be re-deployed so it has been left as is\n error EmptyTokenTranferGasLimit(address token);\n\n // AccountUtils errors\n error EmptyAccount();\n error EmptyReceiver();\n error DataListLengthExceeded();\n\n // ClaimHandler errors\n error EmptyAmount();\n error EmptyClaimableAmount(address token);\n error InvalidToken(address token);\n error InvalidParams(string reason);\n error InsufficientFunds(address token);\n error InvalidClaimTermsSignature(address recoveredSigner, address expectedSigner);\n error InvalidClaimTermsSignatureForContract(address expectedSigner);\n error DuplicateClaimTerms(uint256 existingDistributionId);\n\n // Array errors\n error CompactedArrayOutOfBounds(\n uint256[] compactedValues,\n uint256 index,\n uint256 slotIndex,\n string label\n );\n\n error ArrayOutOfBoundsUint256(\n uint256[] values,\n uint256 index,\n string label\n );\n\n error ArrayOutOfBoundsBytes(\n bytes[] values,\n uint256 index,\n string label\n );\n\n // WithdrawalHandler errors\n error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);\n\n // WithdrawalStoreUtils errors\n error WithdrawalNotFound(bytes32 key);\n\n // WithdrawalUtils errors\n error EmptyWithdrawal();\n error EmptyWithdrawalAmount();\n error MinLongTokens(uint256 received, uint256 expected);\n error MinShortTokens(uint256 received, uint256 expected);\n error InsufficientMarketTokens(uint256 balance, uint256 expected);\n error InvalidPoolValueForWithdrawal(int256 poolValue);\n error MaxLendableFactorForWithdrawalsExceeded(uint256 poolUsd, uint256 maxLendableUsd, uint256 lentUsd);\n\n // Uint256Mask errors\n error MaskIndexOutOfBounds(uint256 index, string label);\n error DuplicatedIndex(uint256 index, string label);\n\n // Cast errors\n error Uint256AsBytesLengthExceeds32Bytes(uint256 length);\n\n // ConfigSyncer errors\n error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);\n error SyncConfigUpdatesDisabledForMarket(address market);\n error SyncConfigUpdatesDisabledForParameter(string parameter);\n error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);\n error SyncConfigInvalidMarketFromData(address market, address marketFromData);\n\n // Reader errors\n error EmptyMarketPrice(address market);\n\n // Multichain errors\n error InvalidTransferRequestsLength();\n error EmptyMultichainTransferInAmount(address account, address token);\n error EmptyMultichainTransferOutAmount(address account, address token);\n error InsufficientMultichainBalance(address account, address token, uint256 balance, uint256 amount);\n error InvalidSrcChainId(uint256 srcChainId);\n error InvalidEid(uint256 eid);\n error InvalidDestinationChainId(uint256 desChainId);\n error TokenPermitsNotAllowedForMultichain();\n error InvalidInitializer();\n error InvalidMultichainProvider(address provider);\n error InvalidMultichainEndpoint(address endpoint);\n error UnableToPayOrderFee();\n error UnableToPayOrderFeeFromCollateral();\n error InvalidBridgeOutToken(address token);\n error InsufficientFee(uint256 feeProvided, uint256 feeRequired);\n\n enum SignatureType {\n Call,\n SubaccountApproval\n }\n\n // Gelato relay errors\n error InvalidSignature(string signatureType);\n error InvalidRecoveredSigner(string signatureType, address recovered, address recoveredFromMinified, address expectedSigner);\n // User sent incorrect fee token or incorrect swap path\n error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);\n error UnexpectedRelayFeeToken(address feeToken, address expectedFeeToken);\n // Contract received unsupported fee token from Gelato relay\n error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);\n error InvalidPermitSpender(address spender, address expectedSpender);\n error InvalidUserDigest(bytes32 digest);\n error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);\n error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);\n error InvalidSubaccountApprovalDesChainId(uint256 desChainId);\n error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);\n error InsufficientRelayFee(uint256 requiredRelayFee, uint256 availableFeeAmount);\n error InvalidSubaccountApprovalSubaccount();\n error NonEmptyExternalCallsForSubaccountOrder();\n\n // EventUtils error\n error EventItemNotFound(string key);\n\n // EdgeOracle verifier errors\n error InvalidTrustedSignerAddress();\n error InvalidEdgeSigner();\n error InvalidEdgeSignature(uint256 recoverError);\n error InvalidEdgeDataStreamBidAsk(address token, uint256 bid, uint256 ask);\n error InvalidEdgeDataStreamPrices(address token, uint256 bid, uint256 ask);\n error InvalidEdgeDataStreamExpo(int256 expo);\n error RelayEmptyBatch();\n error RelayCalldataTooLong(uint256 calldataLength);\n error InvalidExternalCalls(uint256 sendTokensLength, uint256 sendAmountsLength);\n error MaxRelayFeeSwapForSubaccountExceeded(uint256 feeUsd, uint256 maxFeeUsd);\n\n // MultichainReader errors\n error InsufficientMultichainNativeFee(uint256 msgValue);\n error EmptyPeer(uint32 eid);\n\n // FeeDistributor errors\n error FeeDistributionAlreadyCompleted(uint256 lastDistributionTime, uint256 startOfCurrentWeek);\n error OutdatedReadResponse(uint256 timestamp);\n error InvalidDistributionState(uint256 distributionStateUint);\n error BridgedAmountNotSufficient(uint256 minRequiredFeeAmount, uint256 currentChainFeeAmount);\n error BridgingTransactionFailed(bytes result);\n error MaxWntReferralRewardsInUsdAmountExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsdAmount);\n error MaxWntReferralRewardsInUsdExceeded(uint256 wntReferralRewardsInUsd, uint256 maxWntReferralRewardsInUsd);\n error MaxEsGmxReferralRewardsAmountExceeded(uint256 tokensForReferralRewards, uint256 maxEsGmxReferralRewards);\n error MaxReferralRewardsExceeded(address token, uint256 cumulativeTransferAmount, uint256 tokensForReferralRewards);\n error MaxWntFromTreasuryExceeded(uint256 maxWntFromTreasury, uint256 additionalWntFromTreasury);\n error KeeperArrayLengthMismatch(uint256 keepersLength, uint256 keeperTargetBalancesLength, uint256 keeperVersionsLength);\n error SendEthToKeeperFailed(address keeper, uint256 sendAmount, bytes result);\n error KeeperAmountMismatch(uint256 wntForKeepers, uint256 wntToKeepers);\n error AttemptedBridgeAmountTooHigh(uint256 minRequiredFeeAmount, uint256 feeAmountCurrentChain, uint256 amountToBridgeOut);\n error InvalidReferralRewardToken(address token);\n error BridgingBalanceArrayMismatch(uint256 balancesLength, uint256 targetBalancesLength);\n error ZeroTreasuryAddress();\n}\n" + }, + "contracts/error/ErrorUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nlibrary ErrorUtils {\n // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577\n function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {\n // If the result length is less than 68, then the transaction either panicked or failed silently\n if (result.length < 68) {\n return (\"\", false);\n }\n\n bytes4 errorSelector = getErrorSelectorFromData(result);\n\n // 0x08c379a0 is the selector for Error(string)\n // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/\n if (errorSelector == bytes4(0x08c379a0)) {\n assembly {\n result := add(result, 0x04)\n }\n\n return (abi.decode(result, (string)), true);\n }\n\n // error may be a custom error, return an empty string for this case\n return (\"\", false);\n }\n\n function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {\n bytes4 errorSelector;\n\n assembly {\n errorSelector := mload(add(data, 0x20))\n }\n\n return errorSelector;\n }\n\n function revertWithParsedMessage(bytes memory result) internal pure {\n (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);\n\n if (hasRevertMessage) {\n revert(revertMessage);\n } else {\n revertWithCustomError(result);\n }\n }\n\n function revertWithCustomError(bytes memory result) internal pure {\n // referenced from https://ethereum.stackexchange.com/a/123588\n uint256 length = result.length;\n assembly {\n revert(add(result, 0x20), length)\n }\n }\n}\n" + }, + "contracts/event/EventEmitter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../role/RoleModule.sol\";\nimport \"./EventUtils.sol\";\n\n// @title EventEmitter\n// @dev Contract to emit events\n// This allows main events to be emitted from a single contract\n// Logic contracts can be updated while re-using the same eventEmitter contract\n// Peripheral services like monitoring or analytics would be able to continue\n// to work without an update and without segregating historical data\ncontract EventEmitter is RoleModule {\n event EventLog(\n address msgSender,\n string eventName,\n string indexed eventNameHash,\n EventUtils.EventLogData eventData\n );\n\n event EventLog1(\n address msgSender,\n string eventName,\n string indexed eventNameHash,\n bytes32 indexed topic1,\n EventUtils.EventLogData eventData\n );\n\n event EventLog2(\n address msgSender,\n string eventName,\n string indexed eventNameHash,\n bytes32 indexed topic1,\n bytes32 indexed topic2,\n EventUtils.EventLogData eventData\n );\n\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n // @dev emit a general event log\n // @param eventName the name of the event\n // @param eventData the event data\n function emitEventLog(\n string memory eventName,\n EventUtils.EventLogData memory eventData\n ) external onlyController {\n emit EventLog(\n msg.sender,\n eventName,\n eventName,\n eventData\n );\n }\n\n // @dev emit a general event log\n // @param eventName the name of the event\n // @param topic1 topic1 for indexing\n // @param eventData the event data\n function emitEventLog1(\n string memory eventName,\n bytes32 topic1,\n EventUtils.EventLogData memory eventData\n ) external onlyController {\n emit EventLog1(\n msg.sender,\n eventName,\n eventName,\n topic1,\n eventData\n );\n }\n\n // @dev emit a general event log\n // @param eventName the name of the event\n // @param topic1 topic1 for indexing\n // @param topic2 topic2 for indexing\n // @param eventData the event data\n function emitEventLog2(\n string memory eventName,\n bytes32 topic1,\n bytes32 topic2,\n EventUtils.EventLogData memory eventData\n ) external onlyController {\n emit EventLog2(\n msg.sender,\n eventName,\n eventName,\n topic1,\n topic2,\n eventData\n );\n }\n\n\n\n // @dev event log for general use\n // @param topic1 event topic 1\n // @param data additional data\n function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {\n uint256 len = data.length;\n assembly {\n log1(add(data, 32), len, topic1)\n }\n }\n\n // @dev event log for general use\n // @param topic1 event topic 1\n // @param topic2 event topic 2\n // @param data additional data\n function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {\n uint256 len = data.length;\n assembly {\n log2(add(data, 32), len, topic1, topic2)\n }\n }\n\n // @dev event log for general use\n // @param topic1 event topic 1\n // @param topic2 event topic 2\n // @param topic3 event topic 3\n // @param data additional data\n function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {\n uint256 len = data.length;\n assembly {\n log3(add(data, 32), len, topic1, topic2, topic3)\n }\n }\n\n // @dev event log for general use\n // @param topic1 event topic 1\n // @param topic2 event topic 2\n // @param topic3 event topic 3\n // @param topic4 event topic 4\n // @param data additional data\n function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {\n uint256 len = data.length;\n assembly {\n log4(add(data, 32), len, topic1, topic2, topic3, topic4)\n }\n }\n}\n" + }, + "contracts/event/EventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/Errors.sol\";\nimport \"../utils/StringUtils.sol\";\n\nlibrary EventUtils {\n\n struct EmitPositionDecreaseParams {\n bytes32 key;\n address account;\n address market;\n address collateralToken;\n bool isLong;\n }\n\n struct EventLogData {\n AddressItems addressItems;\n UintItems uintItems;\n IntItems intItems;\n BoolItems boolItems;\n Bytes32Items bytes32Items;\n BytesItems bytesItems;\n StringItems stringItems;\n }\n\n struct AddressItems {\n AddressKeyValue[] items;\n AddressArrayKeyValue[] arrayItems;\n }\n\n struct UintItems {\n UintKeyValue[] items;\n UintArrayKeyValue[] arrayItems;\n }\n\n struct IntItems {\n IntKeyValue[] items;\n IntArrayKeyValue[] arrayItems;\n }\n\n struct BoolItems {\n BoolKeyValue[] items;\n BoolArrayKeyValue[] arrayItems;\n }\n\n struct Bytes32Items {\n Bytes32KeyValue[] items;\n Bytes32ArrayKeyValue[] arrayItems;\n }\n\n struct BytesItems {\n BytesKeyValue[] items;\n BytesArrayKeyValue[] arrayItems;\n }\n\n struct StringItems {\n StringKeyValue[] items;\n StringArrayKeyValue[] arrayItems;\n }\n\n struct AddressKeyValue {\n string key;\n address value;\n }\n\n struct AddressArrayKeyValue {\n string key;\n address[] value;\n }\n\n struct UintKeyValue {\n string key;\n uint256 value;\n }\n\n struct UintArrayKeyValue {\n string key;\n uint256[] value;\n }\n\n struct IntKeyValue {\n string key;\n int256 value;\n }\n\n struct IntArrayKeyValue {\n string key;\n int256[] value;\n }\n\n struct BoolKeyValue {\n string key;\n bool value;\n }\n\n struct BoolArrayKeyValue {\n string key;\n bool[] value;\n }\n\n struct Bytes32KeyValue {\n string key;\n bytes32 value;\n }\n\n struct Bytes32ArrayKeyValue {\n string key;\n bytes32[] value;\n }\n\n struct BytesKeyValue {\n string key;\n bytes value;\n }\n\n struct BytesArrayKeyValue {\n string key;\n bytes[] value;\n }\n\n struct StringKeyValue {\n string key;\n string value;\n }\n\n struct StringArrayKeyValue {\n string key;\n string[] value;\n }\n\n function initItems(AddressItems memory items, uint256 size) internal pure {\n items.items = new EventUtils.AddressKeyValue[](size);\n }\n\n function initArrayItems(AddressItems memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);\n }\n\n function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(AddressItems memory addresses, string memory key) external pure returns(address) {\n (bool found, address value) = getWithoutRevert(addresses, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(AddressItems memory addresses, string memory key) public pure returns(bool, address) {\n for (uint i = 0; i < addresses.items.length; i++) {\n if (compareStrings(addresses.items[i].key, key)) {\n return (true, addresses.items[i].value);\n }\n }\n return (false, address(0));\n }\n\n function getArray(AddressItems memory addresses, string memory key) external pure\n returns(address[] memory) {\n (bool found, address[] memory value) = getArrayWithoutRevert(addresses, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(AddressItems memory addresses, string memory key) public pure\n returns(bool, address[] memory) {\n for (uint i = 0; i < addresses.arrayItems.length; i++) {\n if (compareStrings(addresses.arrayItems[i].key, key)) {\n return (true, addresses.arrayItems[i].value);\n }\n }\n address[] memory empty;\n return (false, empty);\n }\n\n function initItems(UintItems memory items, uint256 size) internal pure {\n items.items = new EventUtils.UintKeyValue[](size);\n }\n\n function initArrayItems(UintItems memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.UintArrayKeyValue[](size);\n }\n\n function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(UintItems memory items, string memory key) external pure returns(uint256) {\n (bool found, uint256 value) = getWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(UintItems memory items, string memory key) public pure returns(bool, uint256) {\n for (uint i = 0; i < items.items.length; i++) {\n if (compareStrings(items.items[i].key, key)) {\n return (true, items.items[i].value);\n }\n }\n return (false, 0);\n }\n\n function getArray(UintItems memory items, string memory key) external pure\n returns(uint256[] memory) {\n (bool found, uint256[] memory value) = getArrayWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(UintItems memory items, string memory key) public pure\n returns(bool, uint256[] memory) {\n for (uint i = 0; i < items.arrayItems.length; i++) {\n if (compareStrings(items.arrayItems[i].key, key)) {\n return (true, items.arrayItems[i].value);\n }\n }\n uint256[] memory empty;\n return (false, empty);\n }\n\n function initItems(IntItems memory items, uint256 size) internal pure {\n items.items = new EventUtils.IntKeyValue[](size);\n }\n\n function initArrayItems(IntItems memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.IntArrayKeyValue[](size);\n }\n\n function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(IntItems memory items, string memory key) external pure returns(int256) {\n (bool found, int256 value) = getWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(IntItems memory items, string memory key) public pure returns(bool, int256) {\n for (uint i = 0; i < items.items.length; i++) {\n if (compareStrings(items.items[i].key, key)) {\n return (true, items.items[i].value);\n }\n }\n return (false, 0);\n }\n\n function getArray(IntItems memory items, string memory key) external pure\n returns(int256[] memory) {\n (bool found, int256[] memory value) = getArrayWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(IntItems memory items, string memory key) public pure\n returns(bool, int256[] memory) {\n for (uint i = 0; i < items.arrayItems.length; i++) {\n if (compareStrings(items.arrayItems[i].key, key)) {\n return (true, items.arrayItems[i].value);\n }\n }\n int256[] memory empty;\n return (false, empty);\n }\n\n function initItems(BoolItems memory items, uint256 size) internal pure {\n items.items = new EventUtils.BoolKeyValue[](size);\n }\n\n function initArrayItems(BoolItems memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);\n }\n\n function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(BoolItems memory items, string memory key) external pure returns(bool) {\n (bool found, bool value) = getWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(BoolItems memory items, string memory key) public pure returns(bool, bool) {\n for (uint i = 0; i < items.items.length; i++) {\n if (compareStrings(items.items[i].key, key)) {\n return (true, items.items[i].value);\n }\n }\n return (false, false);\n }\n\n function getArray(BoolItems memory items, string memory key) external pure\n returns(bool[] memory) {\n (bool found, bool[] memory value) = getArrayWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(BoolItems memory items, string memory key) public pure\n returns(bool, bool[] memory) {\n for (uint i = 0; i < items.arrayItems.length; i++) {\n if (compareStrings(items.arrayItems[i].key, key)) {\n return (true, items.arrayItems[i].value);\n }\n }\n bool[] memory empty;\n return (false, empty);\n }\n\n function initItems(Bytes32Items memory items, uint256 size) internal pure {\n items.items = new EventUtils.Bytes32KeyValue[](size);\n }\n\n function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);\n }\n\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(Bytes32Items memory items, string memory key) external pure returns(bytes32) {\n (bool found, bytes32 value) = getWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(Bytes32Items memory items, string memory key) public pure returns(bool, bytes32) {\n for (uint i = 0; i < items.items.length; i++) {\n if (compareStrings(items.items[i].key, key)) {\n return (true, items.items[i].value);\n }\n }\n return (false, 0);\n }\n\n function getArray(Bytes32Items memory items, string memory key) external pure\n returns(bytes32[] memory) {\n (bool found, bytes32[] memory value) = getArrayWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(Bytes32Items memory items, string memory key) public pure\n returns(bool, bytes32[] memory) {\n for (uint i = 0; i < items.arrayItems.length; i++) {\n if (compareStrings(items.arrayItems[i].key, key)) {\n return (true, items.arrayItems[i].value);\n }\n }\n bytes32[] memory empty;\n return (false, empty);\n }\n\n function initItems(BytesItems memory items, uint256 size) internal pure {\n items.items = new EventUtils.BytesKeyValue[](size);\n }\n\n function initArrayItems(BytesItems memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);\n }\n\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(BytesItems memory items, string memory key) external pure returns(bytes memory) {\n (bool found, bytes memory value) = getWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(BytesItems memory items, string memory key) public pure returns(bool, bytes memory) {\n for (uint i = 0; i < items.items.length; i++) {\n if (compareStrings(items.items[i].key, key)) {\n return (true, items.items[i].value);\n }\n }\n return (false, \"\");\n }\n\n function getArray(BytesItems memory items, string memory key) external pure\n returns(bytes[] memory) {\n (bool found, bytes[] memory value) = getArrayWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(BytesItems memory items, string memory key) public pure\n returns(bool, bytes[] memory) {\n for (uint i = 0; i < items.arrayItems.length; i++) {\n if (compareStrings(items.arrayItems[i].key, key)) {\n return (true, items.arrayItems[i].value);\n }\n }\n bytes[] memory empty;\n return (false, empty);\n }\n\n function initItems(StringItems memory items, uint256 size) internal pure {\n items.items = new EventUtils.StringKeyValue[](size);\n }\n\n function initArrayItems(StringItems memory items, uint256 size) internal pure {\n items.arrayItems = new EventUtils.StringArrayKeyValue[](size);\n }\n\n function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {\n items.items[index].key = key;\n items.items[index].value = value;\n }\n\n function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {\n items.arrayItems[index].key = key;\n items.arrayItems[index].value = value;\n }\n\n function get(StringItems memory items, string memory key) external pure returns(string memory) {\n (bool found, string memory value) = getWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getWithoutRevert(StringItems memory items, string memory key) public pure returns(bool, string memory) {\n for (uint i = 0; i < items.items.length; i++) {\n if (compareStrings(items.items[i].key, key)) {\n return (true, items.items[i].value);\n }\n }\n return (false, \"\");\n }\n\n function getArray(StringItems memory items, string memory key) external pure\n returns(string[] memory) {\n (bool found, string[] memory value) = getArrayWithoutRevert(items, key);\n if (!found) {\n revert Errors.EventItemNotFound(key);\n }\n return value;\n }\n\n function getArrayWithoutRevert(StringItems memory items, string memory key) public pure\n returns(bool, string[] memory) {\n for (uint i = 0; i < items.arrayItems.length; i++) {\n if (compareStrings(items.arrayItems[i].key, key)) {\n return (true, items.arrayItems[i].value);\n }\n }\n string[] memory empty;\n return (false, empty);\n }\n\n function compareStrings(string memory a, string memory b) public pure returns (bool) {\n return StringUtils.compareStrings(a, b);\n }\n}\n" + }, + "contracts/exchange/AdlHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseOrderHandler.sol\";\nimport \"../adl/AdlUtils.sol\";\nimport \"../order/ExecuteOrderUtils.sol\";\n\n// @title AdlHandler\n// @dev Contract to handle adls\ncontract AdlHandler is BaseOrderHandler {\n using SafeCast for uint256;\n using SafeCast for int256;\n using Order for Order.Props;\n using Array for uint256[];\n\n // @dev ExecuteAdlCache struct used in executeAdl to avoid\n // stack too deep errors\n struct ExecuteAdlCache {\n uint256 startingGas;\n bytes32 key;\n bool shouldAllowAdl;\n uint256 maxPnlFactorForAdl;\n int256 pnlToPoolFactor;\n int256 nextPnlToPoolFactor;\n uint256 minPnlFactorForAdl;\n }\n\n IOrderExecutor public immutable decreaseOrderExecutor;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IReferralStorage _referralStorage,\n IOrderExecutor _decreaseOrderExecutor\n ) BaseOrderHandler(\n _roleStore,\n _dataStore,\n _eventEmitter,\n _oracle,\n MultichainVault(_multichainVault),\n _orderVault,\n _swapHandler,\n _referralStorage\n ) {\n decreaseOrderExecutor = _decreaseOrderExecutor;\n }\n\n // @dev checks the ADL state to update the isAdlEnabled flag\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @param oracleParams OracleUtils.SetPricesParams\n function updateAdlState(\n address market,\n bool isLong,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external\n globalNonReentrant\n onlyAdlKeeper\n withOraclePrices(oracleParams)\n {\n AdlUtils.updateAdlState(\n dataStore,\n eventEmitter,\n oracle,\n market,\n isLong\n );\n }\n\n // @dev auto-deleverages a position\n // there is no validation that ADL is executed in order of position profit\n // or position size, this is due to the limitation of the gas overhead\n // required to check this ordering\n //\n // ADL keepers could be separately incentivised using a rebate based on\n // position profit, this is not implemented within the contracts at the moment\n //\n // @param account the position's account\n // @param market the position's market\n // @param collateralToken the position's collateralToken\n // @param isLong whether the position is long or short\n // @param sizeDeltaUsd the size to reduce the position by\n // @param oracleParams OracleUtils.SetPricesParams\n function executeAdl(\n address account,\n address market,\n address collateralToken,\n bool isLong,\n uint256 sizeDeltaUsd,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external\n globalNonReentrant\n onlyAdlKeeper\n withOraclePrices(oracleParams)\n {\n ExecuteAdlCache memory cache;\n\n cache.startingGas = gasleft();\n\n AdlUtils.validateAdl(\n dataStore,\n oracle,\n market,\n isLong\n );\n\n (cache.shouldAllowAdl, cache.pnlToPoolFactor, cache.maxPnlFactorForAdl) = MarketUtils.isPnlFactorExceeded(\n dataStore,\n oracle,\n market,\n isLong,\n Keys.MAX_PNL_FACTOR_FOR_ADL\n );\n\n if (!cache.shouldAllowAdl) {\n revert Errors.AdlNotRequired(cache.pnlToPoolFactor, cache.maxPnlFactorForAdl);\n }\n\n cache.key = AdlUtils.createAdlOrder(\n AdlUtils.CreateAdlOrderParams(\n dataStore,\n eventEmitter,\n account,\n market,\n collateralToken,\n isLong,\n sizeDeltaUsd,\n oracle.minTimestamp() // updatedAtTime\n )\n );\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, cache.key);\n\n BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams(\n cache.key,\n order,\n msg.sender,\n cache.startingGas,\n Order.SecondaryOrderType.Adl\n );\n\n FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeAdlFeatureDisabledKey(address(this), uint256(params.order.orderType())));\n\n ExecuteOrderUtils.executeOrder(decreaseOrderExecutor, params);\n\n // validate that the ratio of pending pnl to pool value was decreased\n cache.nextPnlToPoolFactor = MarketUtils.getPnlToPoolFactor(dataStore, oracle, market, isLong, true);\n if (cache.nextPnlToPoolFactor >= cache.pnlToPoolFactor) {\n revert Errors.InvalidAdl(cache.nextPnlToPoolFactor, cache.pnlToPoolFactor);\n }\n\n cache.minPnlFactorForAdl = MarketUtils.getMinPnlFactorAfterAdl(dataStore, market, isLong);\n\n if (cache.nextPnlToPoolFactor < cache.minPnlFactorForAdl.toInt256()) {\n revert Errors.PnlOvercorrected(cache.nextPnlToPoolFactor, cache.minPnlFactorForAdl);\n }\n }\n}\n" + }, + "contracts/exchange/BaseHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../oracle/OracleModule.sol\";\nimport \"../role/RoleModule.sol\";\nimport \"../utils/GlobalReentrancyGuard.sol\";\nimport \"../error/ErrorUtils.sol\";\nimport \"../feature/FeatureUtils.sol\";\nimport \"../chain/Chain.sol\";\n\ncontract BaseHandler is RoleModule, GlobalReentrancyGuard, OracleModule {\n EventEmitter public immutable eventEmitter;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle\n ) RoleModule(_roleStore) GlobalReentrancyGuard(_dataStore) OracleModule(_oracle) {\n eventEmitter = _eventEmitter;\n }\n\n receive() external payable {\n address wnt = dataStore.getAddress(Keys.WNT);\n if (msg.sender != wnt) {\n revert Errors.InvalidNativeTokenSender(msg.sender);\n }\n }\n\n function validateRequestCancellation(\n uint256 createdAtTime,\n string memory requestType\n ) internal view {\n uint256 requestExpirationTime = dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);\n uint256 requestAge = Chain.currentTimestamp() - createdAtTime;\n if (requestAge < requestExpirationTime) {\n revert Errors.RequestNotYetCancellable(requestAge, requestExpirationTime, requestType);\n }\n }\n\n function validateNonKeeperError(bytes4 errorSelector, bytes memory reasonBytes) internal pure {\n if (\n OracleUtils.isOracleError(errorSelector) ||\n errorSelector == Errors.DisabledFeature.selector ||\n errorSelector == Errors.InsufficientGasLeftForCallback.selector ||\n errorSelector == Errors.InsufficientGasForCancellation.selector\n ) {\n ErrorUtils.revertWithCustomError(reasonBytes);\n }\n }\n\n function validateDataListLength(uint256 dataLength) internal view {\n uint256 maxDataLength = dataStore.getUint(Keys.MAX_DATA_LENGTH);\n if (dataLength > maxDataLength) {\n revert Errors.MaxDataListLengthExceeded(dataLength, maxDataLength);\n }\n }\n}\n" + }, + "contracts/exchange/BaseOrderHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseHandler.sol\";\n\nimport \"../market/MarketUtils.sol\";\nimport \"../order/BaseOrderUtils.sol\";\nimport \"../order/OrderVault.sol\";\nimport \"../order/Order.sol\";\nimport \"../swap/ISwapHandler.sol\";\n\nimport \"../referral/IReferralStorage.sol\";\n\n// @title BaseOrderHandler\n// @dev Base contract for shared order handler functions\ncontract BaseOrderHandler is BaseHandler {\n using SafeCast for uint256;\n using Order for Order.Props;\n using Array for uint256[];\n\n MultichainVault public immutable multichainVault;\n OrderVault public immutable orderVault;\n ISwapHandler public immutable swapHandler;\n IReferralStorage public immutable referralStorage;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IReferralStorage _referralStorage\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n orderVault = _orderVault;\n swapHandler = _swapHandler;\n referralStorage = _referralStorage;\n }\n\n // @dev get the BaseOrderUtils.ExecuteOrderParams to execute an order\n // @return the required BaseOrderUtils.ExecuteOrderParams params to execute the order\n function _getExecuteOrderParams(\n bytes32 key,\n Order.Props memory order,\n address keeper,\n uint256 startingGas,\n Order.SecondaryOrderType secondaryOrderType\n ) internal view returns (BaseOrderUtils.ExecuteOrderParams memory) {\n BaseOrderUtils.ExecuteOrderParams memory params;\n\n params.key = key;\n params.order = order;\n params.swapPathMarkets = MarketUtils.getSwapPathMarkets(\n dataStore,\n params.order.swapPath()\n );\n\n params.contracts.dataStore = dataStore;\n params.contracts.eventEmitter = eventEmitter;\n params.contracts.multichainVault = multichainVault;\n params.contracts.orderVault = orderVault;\n params.contracts.oracle = oracle;\n params.contracts.swapHandler = swapHandler;\n params.contracts.referralStorage = referralStorage;\n\n params.minOracleTimestamp = oracle.minTimestamp();\n params.maxOracleTimestamp = oracle.maxTimestamp();\n\n if (params.order.market() != address(0)) {\n params.market = MarketUtils.getEnabledMarket(params.contracts.dataStore, params.order.market());\n }\n\n params.keeper = keeper;\n params.startingGas = startingGas;\n\n params.secondaryOrderType = secondaryOrderType;\n\n return params;\n }\n}\n" + }, + "contracts/exchange/DepositHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./BaseHandler.sol\";\n\nimport \"../market/Market.sol\";\n\nimport \"../deposit/Deposit.sol\";\nimport \"../deposit/DepositVault.sol\";\nimport \"../deposit/DepositUtils.sol\";\nimport \"../deposit/ExecuteDepositUtils.sol\";\n\nimport \"../multichain/MultichainVault.sol\";\nimport \"../multichain/IMultichainTransferRouter.sol\";\n\nimport \"./IDepositHandler.sol\";\n\n// @title DepositHandler\n// @dev Contract to handle creation, execution and cancellation of deposits\ncontract DepositHandler is IDepositHandler, BaseHandler, ReentrancyGuard {\n using Deposit for Deposit.Props;\n\n DepositVault public immutable depositVault;\n MultichainVault public immutable multichainVault;\n IMultichainTransferRouter public immutable multichainTransferRouter;\n ISwapHandler public immutable swapHandler;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n IMultichainTransferRouter _multichainTransferRouter,\n DepositVault _depositVault,\n ISwapHandler _swapHandler\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n multichainTransferRouter = _multichainTransferRouter;\n depositVault = _depositVault;\n swapHandler = _swapHandler;\n }\n\n // @dev creates a deposit in the deposit store\n // @param account the depositing account\n // @param srcChainId the source chain id\n // @param params IDepositUtils.CreateDepositParams\n function createDeposit(\n address account,\n uint256 srcChainId,\n IDepositUtils.CreateDepositParams calldata params\n ) external override globalNonReentrant onlyController returns (bytes32) {\n FeatureUtils.validateFeature(dataStore, Keys.createDepositFeatureDisabledKey(address(this)));\n validateDataListLength(params.dataList.length);\n\n return DepositUtils.createDeposit(\n dataStore,\n eventEmitter,\n depositVault,\n account,\n srcChainId,\n params\n );\n }\n\n // @dev cancels a deposit\n // @param key the deposit key\n function cancelDeposit(bytes32 key) external override globalNonReentrant onlyController {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n Deposit.Props memory deposit = DepositStoreUtils.get(_dataStore, key);\n\n FeatureUtils.validateFeature(_dataStore, Keys.cancelDepositFeatureDisabledKey(address(this)));\n\n validateRequestCancellation(\n deposit.updatedAtTime(),\n \"Deposit\"\n );\n\n DepositUtils.cancelDeposit(\n _dataStore,\n eventEmitter,\n multichainVault,\n depositVault,\n key,\n deposit.account(),\n startingGas,\n Keys.USER_INITIATED_CANCEL,\n \"\"\n );\n }\n\n // @dev executes a deposit\n // @param key the key of the deposit to execute\n // @param oracleParams OracleUtils.SetPricesParams\n function executeDeposit(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external\n globalNonReentrant\n onlyOrderKeeper\n withOraclePrices(oracleParams)\n {\n uint256 startingGas = gasleft();\n\n Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);\n uint256 estimatedGasLimit = GasUtils.estimateExecuteDepositGasLimit(dataStore, deposit);\n GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);\n\n try this._executeDeposit{ gas: executionGas }(\n key,\n deposit,\n msg.sender\n ) {\n } catch (bytes memory reasonBytes) {\n _handleDepositError(\n key,\n startingGas,\n reasonBytes\n );\n }\n }\n\n // @dev The executeDepositFromController function was introduced to reduce cross-contract dependencies.\n // This adds an extra external call during deposit execution (e.g. during shifts), which does not adjust\n // params.startingGas for the 63/64 gas rule. As a result, gas usage may be overestimated.\n // Currently, this has no net impact because deposits using this path have executionFee set to zero,\n // so no gas-based fee is charged. If future uses of this function include deposits with a nonzero\n // executionFee, the lack of gas correction should be revisited.\n function executeDepositFromController(\n IExecuteDepositUtils.ExecuteDepositParams calldata executeDepositParams,\n Deposit.Props calldata deposit\n ) external nonReentrant onlyController returns (uint256) {\n FeatureUtils.validateFeature(dataStore, Keys.executeDepositFeatureDisabledKey(address(this)));\n return ExecuteDepositUtils.executeDeposit(executeDepositParams, deposit);\n }\n\n // @dev simulate execution of a deposit to check for any errors\n // @param key the deposit key\n // @param params OracleUtils.SimulatePricesParams\n function simulateExecuteDeposit(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params\n ) external\n override\n onlyController\n withSimulatedOraclePrices(params)\n globalNonReentrant\n {\n Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);\n\n this._executeDeposit(\n key,\n deposit,\n msg.sender\n );\n }\n\n // @dev executes a deposit\n // @param oracleParams OracleUtils.SetPricesParams\n // @param keeper the keeper executing the deposit\n // @param startingGas the starting gas\n function _executeDeposit(\n bytes32 key,\n Deposit.Props memory deposit,\n address keeper\n ) external onlySelf {\n uint256 startingGas = gasleft();\n\n FeatureUtils.validateFeature(dataStore, Keys.executeDepositFeatureDisabledKey(address(this)));\n\n IExecuteDepositUtils.ExecuteDepositParams memory params = IExecuteDepositUtils.ExecuteDepositParams(\n dataStore,\n eventEmitter,\n multichainVault,\n multichainTransferRouter,\n depositVault,\n oracle,\n swapHandler,\n key,\n keeper,\n startingGas,\n ISwapPricingUtils.SwapPricingType.Deposit,\n true // includeVirtualInventoryImpact\n );\n\n ExecuteDepositUtils.executeDeposit(params, deposit);\n }\n\n // @dev handle errors from deposits\n // @param key the deposit key\n // @param startingGas the starting gas of the txn\n // @param reasonBytes the reason bytes of the error\n function _handleDepositError(\n bytes32 key,\n uint256 startingGas,\n bytes memory reasonBytes\n ) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n\n DepositUtils.cancelDeposit(\n dataStore,\n eventEmitter,\n multichainVault,\n depositVault,\n key,\n msg.sender,\n startingGas,\n reason,\n reasonBytes\n );\n }\n}\n" + }, + "contracts/exchange/GlvDepositHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./IGlvDepositHandler.sol\";\nimport \"./BaseHandler.sol\";\n\nimport \"../glv/glvDeposit/GlvDepositUtils.sol\";\nimport \"../glv/glvDeposit/ExecuteGlvDepositUtils.sol\";\n\ncontract GlvDepositHandler is IGlvDepositHandler, BaseHandler, ReentrancyGuard {\n using GlvDeposit for GlvDeposit.Props;\n\n MultichainVault public immutable multichainVault;\n IMultichainTransferRouter public immutable multichainTransferRouter;\n GlvVault public immutable glvVault;\n ISwapHandler public immutable swapHandler;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n IMultichainTransferRouter _multichainTransferRouter,\n GlvVault _glvVault,\n ISwapHandler _swapHandler\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n multichainTransferRouter = _multichainTransferRouter;\n glvVault = _glvVault;\n swapHandler = _swapHandler;\n }\n\n function createGlvDeposit(\n address account,\n uint256 srcChainId,\n IGlvDepositUtils.CreateGlvDepositParams calldata params\n ) external globalNonReentrant onlyController returns (bytes32) {\n FeatureUtils.validateFeature(dataStore, Keys.createGlvDepositFeatureDisabledKey(address(this)));\n validateDataListLength(params.dataList.length);\n\n return GlvDepositUtils.createGlvDeposit(dataStore, eventEmitter, glvVault, account, srcChainId, params);\n }\n\n // @key glvDeposit key\n // @oracleParams prices for all markets in GLV are required\n function executeGlvDeposit(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external globalNonReentrant onlyOrderKeeper withOraclePrices(oracleParams) {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(_dataStore, key);\n uint256 marketCount = GlvUtils.getGlvMarketCount(_dataStore, glvDeposit.glv());\n uint256 estimatedGasLimit = GasUtils.estimateExecuteGlvDepositGasLimit(_dataStore, glvDeposit, marketCount);\n GasUtils.validateExecutionGas(_dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(_dataStore, startingGas);\n\n try this._executeGlvDeposit{gas: executionGas}(key, glvDeposit, msg.sender) {} catch (\n bytes memory reasonBytes\n ) {\n _handleGlvDepositError(key, startingGas, reasonBytes);\n }\n }\n\n function _executeGlvDeposit(bytes32 key, GlvDeposit.Props memory glvDeposit, address keeper) external onlySelf {\n uint256 startingGas = gasleft();\n\n FeatureUtils.validateFeature(dataStore, Keys.executeGlvDepositFeatureDisabledKey(address(this)));\n\n ExecuteGlvDepositUtils.ExecuteGlvDepositParams memory params = ExecuteGlvDepositUtils.ExecuteGlvDepositParams({\n key: key,\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n multichainTransferRouter: multichainTransferRouter,\n glvVault: glvVault,\n oracle: oracle,\n swapHandler: swapHandler,\n startingGas: startingGas,\n keeper: keeper\n });\n\n ExecuteGlvDepositUtils.executeGlvDeposit(params, glvDeposit);\n }\n\n function _handleGlvDepositError(bytes32 key, uint256 startingGas, bytes memory reasonBytes) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n (string memory reason /* bool hasRevertMessage */, ) = ErrorUtils.getRevertMessage(reasonBytes);\n\n GlvDepositUtils.CancelGlvDepositParams memory params = GlvDepositUtils.CancelGlvDepositParams({\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n glvVault: glvVault,\n key: key,\n keeper: msg.sender,\n startingGas: startingGas,\n reason: reason,\n reasonBytes: reasonBytes\n });\n GlvDepositUtils.cancelGlvDeposit(params);\n }\n\n function cancelGlvDeposit(bytes32 key) external globalNonReentrant onlyController {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n FeatureUtils.validateFeature(_dataStore, Keys.cancelGlvDepositFeatureDisabledKey(address(this)));\n\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(_dataStore, key);\n validateRequestCancellation(glvDeposit.updatedAtTime(), \"GlvDeposit\");\n\n GlvDepositUtils.CancelGlvDepositParams memory params = GlvDepositUtils.CancelGlvDepositParams({\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n glvVault: glvVault,\n key: key,\n keeper: glvDeposit.account(),\n startingGas: startingGas,\n reason: Keys.USER_INITIATED_CANCEL,\n reasonBytes: \"\"\n });\n GlvDepositUtils.cancelGlvDeposit(params);\n }\n\n function simulateExecuteGlvDeposit(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params\n ) external onlyController withSimulatedOraclePrices(params) globalNonReentrant {\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(dataStore, key);\n\n this._executeGlvDeposit(key, glvDeposit, msg.sender);\n }\n}\n" + }, + "contracts/exchange/GlvShiftHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./BaseHandler.sol\";\n\nimport \"../glv/glvShift/GlvShiftUtils.sol\";\n\ncontract GlvShiftHandler is BaseHandler, ReentrancyGuard {\n using GlvShift for GlvShift.Props;\n\n MultichainVault public immutable multichainVault;\n GlvVault public immutable glvVault;\n ShiftVault public immutable shiftVault;\n IDepositHandler public immutable depositHandler;\n IWithdrawalHandler public immutable withdrawalHandler;\n ISwapHandler public immutable swapHandler;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n GlvVault _glvVault,\n ShiftVault _shiftVault,\n IDepositHandler _depositHandler,\n IWithdrawalHandler _withdrawalHandler,\n ISwapHandler _swapHandler\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n glvVault = _glvVault;\n shiftVault = _shiftVault;\n depositHandler = _depositHandler;\n withdrawalHandler = _withdrawalHandler;\n swapHandler = _swapHandler;\n }\n\n function createGlvShift(\n GlvShiftUtils.CreateGlvShiftParams memory params\n ) external globalNonReentrant onlyOrderKeeper returns (bytes32) {\n FeatureUtils.validateFeature(dataStore, Keys.createGlvShiftFeatureDisabledKey(address(this)));\n\n return GlvShiftUtils.createGlvShift(dataStore, eventEmitter, params);\n }\n\n // @key glvDeposit key\n // @oracleParams prices for `fromMarket` and `toMarket` are required\n function executeGlvShift(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external globalNonReentrant onlyOrderKeeper withOraclePrices(oracleParams) {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n\n GlvShift.Props memory glvShift = GlvShiftStoreUtils.get(_dataStore, key);\n uint256 estimatedGasLimit = GasUtils.estimateExecuteGlvShiftGasLimit(_dataStore);\n GasUtils.validateExecutionGas(_dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(_dataStore, startingGas);\n\n try this._executeGlvShift{gas: executionGas}(key, glvShift, msg.sender) {} catch (bytes memory reasonBytes) {\n _handleGlvShiftError(key, reasonBytes);\n }\n }\n\n function _executeGlvShift(bytes32 key, GlvShift.Props memory glvShift, address keeper) external onlySelf {\n FeatureUtils.validateFeature(dataStore, Keys.executeGlvShiftFeatureDisabledKey(address(this)));\n\n GlvShiftUtils.ExecuteGlvShiftParams memory params = GlvShiftUtils.ExecuteGlvShiftParams({\n key: key,\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n shiftVault: shiftVault,\n glvVault: glvVault,\n depositHandler: depositHandler,\n withdrawalHandler: withdrawalHandler,\n swapHandler: swapHandler,\n oracle: oracle,\n keeper: keeper\n });\n\n GlvShiftUtils.executeGlvShift(params, glvShift);\n }\n\n function _handleGlvShiftError(bytes32 key, bytes memory reasonBytes) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n (string memory reason /* bool hasRevertMessage */, ) = ErrorUtils.getRevertMessage(reasonBytes);\n\n GlvShiftUtils.cancelGlvShift(\n dataStore,\n eventEmitter,\n key,\n reason,\n reasonBytes\n );\n }\n\n function addMarketToGlv(address glv, address market) external globalNonReentrant onlyConfigKeeper {\n GlvUtils.addMarketToGlv(dataStore, eventEmitter, glv, market);\n }\n\n function removeMarketFromGlv(address glv, address market) external globalNonReentrant onlyConfigKeeper {\n GlvUtils.removeMarketFromGlv(dataStore, eventEmitter, glv, market);\n }\n}\n" + }, + "contracts/exchange/GlvWithdrawalHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./IGlvWithdrawalHandler.sol\";\nimport \"./BaseHandler.sol\";\n\nimport \"../glv/glvWithdrawal/GlvWithdrawalUtils.sol\";\nimport \"../multichain/IMultichainTransferRouter.sol\";\n\ncontract GlvWithdrawalHandler is IGlvWithdrawalHandler, BaseHandler, ReentrancyGuard {\n using GlvWithdrawal for GlvWithdrawal.Props;\n\n MultichainVault public immutable multichainVault;\n IMultichainTransferRouter public immutable multichainTransferRouter;\n GlvVault public immutable glvVault;\n ISwapHandler public immutable swapHandler;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n IMultichainTransferRouter _multichainTransferRouter,\n GlvVault _glvVault,\n ISwapHandler _swapHandler\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n multichainTransferRouter = _multichainTransferRouter;\n glvVault = _glvVault;\n swapHandler = _swapHandler;\n }\n\n function createGlvWithdrawal(\n address account,\n uint256 srcChainId,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams calldata params\n ) external globalNonReentrant onlyController returns (bytes32) {\n DataStore _dataStore = dataStore;\n FeatureUtils.validateFeature(_dataStore, Keys.createGlvWithdrawalFeatureDisabledKey(address(this)));\n validateDataListLength(params.dataList.length);\n\n return GlvWithdrawalUtils.createGlvWithdrawal(_dataStore, eventEmitter, glvVault, account, srcChainId, params);\n }\n\n // @key glvDeposit key\n // @oracleParams prices for all markets in GLV are required\n function executeGlvWithdrawal(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external globalNonReentrant onlyOrderKeeper withOraclePrices(oracleParams) {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(_dataStore, key);\n uint256 marketCount = GlvUtils.getGlvMarketCount(_dataStore, glvWithdrawal.glv());\n uint256 estimatedGasLimit = GasUtils.estimateExecuteGlvWithdrawalGasLimit(\n _dataStore,\n glvWithdrawal,\n marketCount\n );\n GasUtils.validateExecutionGas(_dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(_dataStore, startingGas);\n\n try this._executeGlvWithdrawal{gas: executionGas}(key, glvWithdrawal, msg.sender) {} catch (\n bytes memory reasonBytes\n ) {\n _handleGlvWithdrawalError(key, startingGas, reasonBytes);\n }\n }\n\n function _executeGlvWithdrawal(\n bytes32 key,\n GlvWithdrawal.Props memory glvWithdrawal,\n address keeper\n ) external onlySelf {\n uint256 startingGas = gasleft();\n\n FeatureUtils.validateFeature(dataStore, Keys.executeGlvWithdrawalFeatureDisabledKey(address(this)));\n\n GlvWithdrawalUtils.ExecuteGlvWithdrawalParams memory params = GlvWithdrawalUtils.ExecuteGlvWithdrawalParams({\n key: key,\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n multichainTransferRouter: multichainTransferRouter,\n glvVault: glvVault,\n oracle: oracle,\n swapHandler: swapHandler,\n startingGas: startingGas,\n keeper: keeper\n });\n\n GlvWithdrawalUtils.executeGlvWithdrawal(params, glvWithdrawal);\n }\n\n function _handleGlvWithdrawalError(bytes32 key, uint256 startingGas, bytes memory reasonBytes) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n (string memory reason /* bool hasRevertMessage */, ) = ErrorUtils.getRevertMessage(reasonBytes);\n\n GlvWithdrawalUtils.CancelGlvWithdrawalParams memory params = GlvWithdrawalUtils.CancelGlvWithdrawalParams({\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n glvVault: glvVault,\n key: key,\n keeper: msg.sender,\n startingGas: startingGas,\n reason: reason,\n reasonBytes: reasonBytes\n });\n GlvWithdrawalUtils.cancelGlvWithdrawal(params);\n }\n\n function cancelGlvWithdrawal(bytes32 key) external globalNonReentrant onlyController {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n FeatureUtils.validateFeature(_dataStore, Keys.cancelGlvWithdrawalFeatureDisabledKey(address(this)));\n\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(_dataStore, key);\n validateRequestCancellation(glvWithdrawal.updatedAtTime(), \"GlvWithdrawal\");\n\n GlvWithdrawalUtils.CancelGlvWithdrawalParams memory params = GlvWithdrawalUtils.CancelGlvWithdrawalParams({\n dataStore: dataStore,\n eventEmitter: eventEmitter,\n multichainVault: multichainVault,\n glvVault: glvVault,\n key: key,\n keeper: glvWithdrawal.account(),\n startingGas: startingGas,\n reason: Keys.USER_INITIATED_CANCEL,\n reasonBytes: \"\"\n });\n GlvWithdrawalUtils.cancelGlvWithdrawal(params);\n }\n\n function simulateExecuteGlvWithdrawal(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params\n ) external onlyController withSimulatedOraclePrices(params) globalNonReentrant {\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(dataStore, key);\n\n this._executeGlvWithdrawal(key, glvWithdrawal, msg.sender);\n }\n}\n" + }, + "contracts/exchange/IDepositHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../deposit/IDepositUtils.sol\";\nimport \"../deposit/IExecuteDepositUtils.sol\";\n\nimport \"../deposit/Deposit.sol\";\nimport \"../oracle/OracleUtils.sol\";\n\ninterface IDepositHandler {\n function createDeposit(address account, uint256 srcChainId, IDepositUtils.CreateDepositParams calldata params) external returns (bytes32);\n function cancelDeposit(bytes32 key) external;\n function simulateExecuteDeposit(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params\n ) external;\n\n function executeDepositFromController(\n IExecuteDepositUtils.ExecuteDepositParams calldata executeDepositParams,\n Deposit.Props calldata deposit\n ) external returns (uint256);\n}\n" + }, + "contracts/exchange/IGlvDepositHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../glv/glvDeposit/IGlvDepositUtils.sol\";\nimport \"../oracle/OracleUtils.sol\";\n\ninterface IGlvDepositHandler {\n function createGlvDeposit(\n address account,\n uint256 srcChainId,\n IGlvDepositUtils.CreateGlvDepositParams calldata params\n ) external returns (bytes32);\n\n function cancelGlvDeposit(bytes32 key) external;\n\n function simulateExecuteGlvDeposit(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;\n}\n" + }, + "contracts/exchange/IGlvWithdrawalHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../glv/glvWithdrawal/IGlvWithdrawalUtils.sol\";\nimport \"../oracle/OracleUtils.sol\";\n\ninterface IGlvWithdrawalHandler {\n function createGlvWithdrawal(\n address account,\n uint256 srcChainId,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams calldata params\n ) external returns (bytes32);\n\n function cancelGlvWithdrawal(bytes32 key) external;\n\n function simulateExecuteGlvWithdrawal(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;\n}\n" + }, + "contracts/exchange/IOrderExecutor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../order/BaseOrderUtils.sol\";\n\ninterface IOrderExecutor {\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) external returns (EventUtils.EventLogData memory);\n}\n" + }, + "contracts/exchange/IOrderHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../order/IBaseOrderUtils.sol\";\nimport \"../oracle/OracleUtils.sol\";\n\ninterface IOrderHandler {\n function createOrder(\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams calldata params,\n bool shouldCapMaxExecutionFee\n ) external returns (bytes32);\n\n function simulateExecuteOrder(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;\n\n function updateOrder(\n bytes32 key,\n uint256 sizeDeltaUsd,\n uint256 acceptablePrice,\n uint256 triggerPrice,\n uint256 minOutputAmount,\n uint256 validFromTime,\n bool autoCancel,\n Order.Props memory order,\n bool shouldCapMaxExecutionFee\n ) external;\n\n function cancelOrder(bytes32 key) external;\n}\n" + }, + "contracts/exchange/IShiftHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../shift/IShiftUtils.sol\";\nimport \"../oracle/OracleUtils.sol\";\n\ninterface IShiftHandler {\n function createShift(address account, uint256 srcChainId, IShiftUtils.CreateShiftParams calldata params) external returns (bytes32);\n function cancelShift(bytes32 key) external;\n function simulateExecuteShift(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;\n}\n" + }, + "contracts/exchange/IWithdrawalHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../withdrawal/IWithdrawalUtils.sol\";\nimport \"../withdrawal/IExecuteWithdrawalUtils.sol\";\nimport \"../withdrawal/Withdrawal.sol\";\nimport \"../oracle/OracleUtils.sol\";\nimport \"../pricing/ISwapPricingUtils.sol\";\n\ninterface IWithdrawalHandler {\n function createWithdrawal(address account, uint256 srcChainId, IWithdrawalUtils.CreateWithdrawalParams calldata params) external returns (bytes32);\n function cancelWithdrawal(bytes32 key) external;\n function executeAtomicWithdrawal(\n address account,\n IWithdrawalUtils.CreateWithdrawalParams calldata params,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external;\n function simulateExecuteWithdrawal(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external;\n function executeWithdrawalFromController(\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams calldata executeWithdrawalParams,\n Withdrawal.Props calldata withdrawal\n )\n external returns (IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory);\n}\n" + }, + "contracts/exchange/LiquidationHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseOrderHandler.sol\";\nimport \"../liquidation/LiquidationUtils.sol\";\nimport \"../order/ExecuteOrderUtils.sol\";\n\n// @title LiquidationHandler\n// @dev Contract to handle liquidations\ncontract LiquidationHandler is BaseOrderHandler {\n using SafeCast for uint256;\n using Order for Order.Props;\n using Array for uint256[];\n\n IOrderExecutor public immutable decreaseOrderExecutor;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IReferralStorage _referralStorage,\n IOrderExecutor _decreaseOrderExecutor\n ) BaseOrderHandler(\n _roleStore,\n _dataStore,\n _eventEmitter,\n _oracle,\n _multichainVault,\n _orderVault,\n _swapHandler,\n _referralStorage\n ) {\n decreaseOrderExecutor = _decreaseOrderExecutor;\n }\n\n // @dev executes a position liquidation\n // @param account the account of the position to liquidate\n // @param market the position's market\n // @param collateralToken the position's collateralToken\n // @param isLong whether the position is long or short\n // @param oracleParams OracleUtils.SetPricesParams\n function executeLiquidation(\n address account,\n address market,\n address collateralToken,\n bool isLong,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external\n globalNonReentrant\n onlyLiquidationKeeper\n withOraclePrices(oracleParams)\n {\n uint256 startingGas = gasleft();\n\n oracle.validateSequencerUp();\n\n bytes32 key = LiquidationUtils.createLiquidationOrder(\n dataStore,\n eventEmitter,\n account,\n market,\n collateralToken,\n isLong\n );\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n\n BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams(\n key,\n order,\n msg.sender,\n startingGas,\n Order.SecondaryOrderType.None\n );\n\n FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeOrderFeatureDisabledKey(address(this), uint256(params.order.orderType())));\n\n ExecuteOrderUtils.executeOrder(decreaseOrderExecutor, params);\n }\n}\n" + }, + "contracts/exchange/OrderHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseOrderHandler.sol\";\nimport \"../error/ErrorUtils.sol\";\nimport \"./IOrderHandler.sol\";\nimport \"../order/OrderUtils.sol\";\nimport \"../order/ExecuteOrderUtils.sol\";\nimport \"../multichain/MultichainVault.sol\";\n\n// @title OrderHandler\n// @dev Contract to handle creation, execution and cancellation of orders\ncontract OrderHandler is IOrderHandler, BaseOrderHandler {\n using SafeCast for uint256;\n using Order for Order.Props;\n using Array for uint256[];\n\n IOrderExecutor public immutable increaseOrderExecutor;\n IOrderExecutor public immutable decreaseOrderExecutor;\n IOrderExecutor public immutable swapOrderExecutor;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IReferralStorage _referralStorage,\n IOrderExecutor _increaseOrderExecutor,\n IOrderExecutor _decreaseOrderExecutor,\n IOrderExecutor _swapOrderExecutor\n ) BaseOrderHandler(\n _roleStore,\n _dataStore,\n _eventEmitter,\n _oracle,\n _multichainVault,\n _orderVault,\n _swapHandler,\n _referralStorage\n ) {\n increaseOrderExecutor = _increaseOrderExecutor;\n decreaseOrderExecutor = _decreaseOrderExecutor;\n swapOrderExecutor = _swapOrderExecutor;\n }\n\n // @dev creates an order in the order store\n // @param account the order's account\n // @param srcChainId the source chain id\n // @param params BaseOrderUtils.CreateOrderParams\n function createOrder(\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams calldata params,\n bool shouldCapMaxExecutionFee\n ) external override globalNonReentrant onlyController returns (bytes32) {\n FeatureUtils.validateFeature(dataStore, Keys.createOrderFeatureDisabledKey(address(this), uint256(params.orderType)));\n validateDataListLength(params.dataList.length);\n\n return OrderUtils.createOrder(\n dataStore,\n eventEmitter,\n orderVault,\n referralStorage,\n account,\n srcChainId,\n params,\n shouldCapMaxExecutionFee\n );\n }\n\n struct UpdateOrderCache {\n address wnt;\n uint256 receivedWnt;\n uint256 estimatedGasLimit;\n uint256 oraclePriceCount;\n }\n\n /**\n * @dev Updates the given order with the specified size delta, acceptable price, and trigger price.\n * The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner\n * of the order, and the order must not be a market order. The size delta, trigger price, and\n * acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is\n * transferred to the contract is added to the order's execution fee. The updated order is then saved\n * in the order store, and an `OrderUpdated` event is emitted.\n *\n * A user may be able to observe exchange prices and prevent order execution by updating the order's\n * trigger price or acceptable price\n *\n * The main front-running concern is if a user knows whether the price is going to move up or down\n * then positions accordingly, e.g. if price is going to move up then the user opens a long position\n *\n * With updating of orders, a user may know that price could be lower and delays the execution of an\n * order by updating it, this should not be a significant front-running concern since it is similar\n * to observing prices then creating a market order as price is decreasing\n *\n * @param key The unique ID of the order to be updated\n * @param sizeDeltaUsd The new size delta for the order\n * @param acceptablePrice The new acceptable price for the order\n * @param triggerPrice The new trigger price for the order\n */\n function updateOrder(\n bytes32 key,\n uint256 sizeDeltaUsd,\n uint256 acceptablePrice,\n uint256 triggerPrice,\n uint256 minOutputAmount,\n uint256 validFromTime,\n bool autoCancel,\n Order.Props memory order,\n bool shouldCapMaxExecutionFee\n ) external override globalNonReentrant onlyController {\n FeatureUtils.validateFeature(dataStore, Keys.updateOrderFeatureDisabledKey(address(this), uint256(order.orderType())));\n\n if (Order.isMarketOrder(order.orderType())) {\n revert Errors.OrderNotUpdatable(uint256(order.orderType()));\n }\n\n // this could happen if the order was created in new contracts that support new order types\n // but the order is being updated in old contracts\n if (!Order.isSupportedOrder(order.orderType())) {\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\n }\n\n if (order.autoCancel() != autoCancel) {\n OrderUtils.updateAutoCancelList(dataStore, key, order, autoCancel);\n OrderUtils.validateTotalCallbackGasLimitForAutoCancelOrders(dataStore, order);\n }\n order.setAutoCancel(autoCancel);\n\n order.setSizeDeltaUsd(sizeDeltaUsd);\n order.setTriggerPrice(triggerPrice);\n order.setAcceptablePrice(acceptablePrice);\n order.setMinOutputAmount(minOutputAmount);\n order.setValidFromTime(validFromTime);\n order.setIsFrozen(false);\n\n UpdateOrderCache memory cache;\n // allow topping up of executionFee as frozen orders\n // will have their executionFee reduced\n cache.wnt = TokenUtils.wnt(dataStore);\n cache.receivedWnt = orderVault.recordTransferIn(cache.wnt);\n\n cache.estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order);\n cache.oraclePriceCount = GasUtils.estimateOrderOraclePriceCount(order.swapPath().length);\n (uint256 executionFee, uint256 executionFeeDiff) = GasUtils.validateAndCapExecutionFee(\n dataStore,\n cache.estimatedGasLimit,\n order.executionFee() + cache.receivedWnt,\n cache.oraclePriceCount,\n shouldCapMaxExecutionFee\n );\n order.setExecutionFee(executionFee);\n\n if (executionFeeDiff != 0) {\n GasUtils.transferExcessiveExecutionFee(dataStore, eventEmitter, orderVault, order.account(), executionFeeDiff);\n }\n\n order.touch();\n\n BaseOrderUtils.validateNonEmptyOrder(order);\n\n OrderStoreUtils.set(dataStore, key, order);\n\n OrderEventUtils.emitOrderUpdated(\n eventEmitter,\n key,\n order\n );\n }\n\n /**\n * @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order\n * type. The caller must be the owner of the order. The order is cancelled by calling the `cancelOrder()`\n * function in the `OrderUtils` contract. This function also records the starting gas amount and the\n * reason for cancellation, which is passed to the `cancelOrder()` function.\n *\n * @param key The unique ID of the order to be cancelled\n */\n function cancelOrder(bytes32 key) external override globalNonReentrant onlyController {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n Order.Props memory order = OrderStoreUtils.get(_dataStore, key);\n\n FeatureUtils.validateFeature(_dataStore, Keys.cancelOrderFeatureDisabledKey(address(this), uint256(order.orderType())));\n\n if (Order.isMarketOrder(order.orderType())) {\n validateRequestCancellation(\n order.updatedAtTime(),\n \"Order\"\n );\n }\n\n OrderUtils.cancelOrder(\n OrderUtils.CancelOrderParams(\n dataStore,\n eventEmitter,\n multichainVault,\n orderVault,\n key,\n order.account(),\n startingGas,\n true, // isExternalCall\n false, // isAutoCancel\n Keys.USER_INITIATED_CANCEL,\n \"\"\n )\n );\n }\n\n // @dev simulate execution of an order to check for any errors\n // @param key the order key\n // @param params OracleUtils.SimulatePricesParams\n function simulateExecuteOrder(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params\n ) external\n override\n onlyController\n withSimulatedOraclePrices(params)\n globalNonReentrant\n {\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n\n this._executeOrder(\n key,\n order,\n msg.sender,\n true // isSimulation\n );\n }\n\n // @dev executes an order\n // @param key the key of the order to execute\n // @param oracleParams OracleUtils.SetPricesParams\n function executeOrder(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external\n globalNonReentrant\n onlyOrderKeeper\n withOraclePrices(oracleParams)\n {\n uint256 startingGas = gasleft();\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order);\n GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);\n\n try this._executeOrder{ gas: executionGas }(\n key,\n order,\n msg.sender,\n false // isSimulation\n ) {\n } catch (bytes memory reasonBytes) {\n _handleOrderError(key, startingGas, reasonBytes);\n }\n }\n\n // @dev executes an order\n // @param key the key of the order to execute\n // @param oracleParams OracleUtils.SetPricesParams\n // @param keeper the keeper executing the order\n // @param startingGas the starting gas\n function _executeOrder(\n bytes32 key,\n Order.Props memory order,\n address keeper,\n bool isSimulation\n ) external onlySelf {\n uint256 startingGas = gasleft();\n\n BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams(\n key,\n order,\n keeper,\n startingGas,\n Order.SecondaryOrderType.None\n );\n // limit swaps require frozen order keeper for execution since on creation it can fail due to output amount\n // which would automatically cause the order to be frozen\n // limit increase and limit / trigger decrease orders may fail due to output amount as well and become frozen\n // but only if their acceptablePrice is reached\n if (!isSimulation && (params.order.isFrozen() || params.order.orderType() == Order.OrderType.LimitSwap)) {\n _validateFrozenOrderKeeper(keeper);\n }\n\n FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeOrderFeatureDisabledKey(address(this), uint256(params.order.orderType())));\n\n ExecuteOrderUtils.executeOrder(getOrderExecutor(params.order.orderType()), params);\n }\n\n function getOrderExecutor(Order.OrderType orderType) internal view returns (IOrderExecutor) {\n if (Order.isIncreaseOrder(orderType)) {\n return increaseOrderExecutor;\n }\n\n if (Order.isDecreaseOrder(orderType)) {\n return decreaseOrderExecutor;\n }\n\n if (Order.isSwapOrder(orderType)) {\n return swapOrderExecutor;\n }\n\n revert Errors.UnsupportedOrderType(uint256(orderType));\n }\n\n // @dev handle a caught order error\n // @param key the order's key\n // @param startingGas the starting gas\n // @param reason the error reason\n // @param reasonKey the hash or the error reason\n function _handleOrderError(\n bytes32 key,\n uint256 startingGas,\n bytes memory reasonBytes\n ) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n bool isMarketOrder = Order.isMarketOrder(order.orderType());\n\n if (\n // if the order is already frozen, revert with the custom error to provide more information\n // on why the order cannot be executed\n order.isFrozen() ||\n // for market orders, the EmptyPosition error should still lead to the\n // order being cancelled\n // for limit, trigger orders, the EmptyPosition error should lead to the transaction\n // being reverted instead\n // if the position is created or increased later, the oracle prices used to fulfill the order\n // must be after the position was last increased, this is validated in DecreaseOrderUtils\n (!isMarketOrder && errorSelector == Errors.EmptyPosition.selector) ||\n errorSelector == Errors.EmptyOrder.selector ||\n // if the order execution feature is disabled, it may be possible\n // for a user to cancel their orders after the feature is re-enabled\n // or they may be able to execute the order at an outdated price\n // depending on the order keeper\n // disabling of features should be a rare occurrence, it may be\n // preferrable to still execute the orders when the feature is re-enabled\n // instead of cancelling / freezing the orders\n // if features are not frequently disabled, the amount of front-running\n // from this should not be significant\n // based on this it may also be advisable to disable the cancelling of orders\n // if the execution of orders is disabled\n errorSelector == Errors.InvalidKeeperForFrozenOrder.selector ||\n errorSelector == Errors.UnsupportedOrderType.selector ||\n // the transaction is reverted for InvalidOrderPrices since the oracle prices\n // do not fulfill the specified trigger price\n errorSelector == Errors.InvalidOrderPrices.selector ||\n // order should not be cancelled or frozen in this case\n // otherwise malicious keepers can cancel orders before valid from time is reached\n errorSelector == Errors.OrderValidFromTimeNotReached.selector\n ) {\n ErrorUtils.revertWithCustomError(reasonBytes);\n }\n\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n\n if (\n isMarketOrder ||\n errorSelector == Errors.InvalidPositionMarket.selector ||\n errorSelector == Errors.InvalidCollateralTokenForMarket.selector ||\n errorSelector == Errors.InvalidPositionSizeValues.selector\n ) {\n OrderUtils.cancelOrder(\n OrderUtils.CancelOrderParams(\n dataStore,\n eventEmitter,\n multichainVault,\n orderVault,\n key,\n msg.sender,\n startingGas,\n true, // isExternalCall\n false, // isAutoCancel\n reason,\n reasonBytes\n )\n );\n\n return;\n }\n\n // freeze unfulfillable orders to prevent the order system from being gamed\n // an example of gaming would be if a user creates a limit order\n // with size greater than the available amount in the pool\n // the user waits for their limit price to be hit, and if price\n // moves in their favour after, they can deposit into the pool\n // to allow the order to be executed then close the order for a profit\n //\n // frozen order keepers are expected to execute orders only if the\n // latest prices match the trigger price\n //\n // a user can also call updateOrder to unfreeze an order\n OrderUtils.freezeOrder(\n dataStore,\n eventEmitter,\n multichainVault,\n orderVault,\n key,\n msg.sender,\n startingGas,\n reason,\n reasonBytes\n );\n }\n\n // @dev validate that the keeper is a frozen order keeper\n // @param keeper address of the keeper\n function _validateFrozenOrderKeeper(address keeper) internal view {\n if (!roleStore.hasRole(keeper, Role.FROZEN_ORDER_KEEPER)) {\n revert Errors.InvalidKeeperForFrozenOrder(keeper);\n }\n }\n}\n" + }, + "contracts/exchange/ShiftHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../exchange/IWithdrawalHandler.sol\";\n\nimport \"../shift/Shift.sol\";\nimport \"../shift/ShiftVault.sol\";\nimport \"../shift/ShiftUtils.sol\";\n\nimport \"./IShiftHandler.sol\";\nimport \"./BaseHandler.sol\";\n\ncontract ShiftHandler is IShiftHandler, BaseHandler {\n using Shift for Shift.Props;\n\n MultichainVault public immutable multichainVault;\n ShiftVault public immutable shiftVault;\n IDepositHandler public depositHandler;\n IWithdrawalHandler public withdrawalHandler;\n ISwapHandler public immutable swapHandler;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n ShiftVault _shiftVault,\n IDepositHandler _depositHandler,\n IWithdrawalHandler _withdrawalHandler,\n ISwapHandler _swapHandler\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n shiftVault = _shiftVault;\n depositHandler = _depositHandler;\n withdrawalHandler = _withdrawalHandler;\n swapHandler = _swapHandler;\n }\n\n function createShift(\n address account,\n uint256 srcChainId,\n IShiftUtils.CreateShiftParams calldata params\n ) external override globalNonReentrant onlyController returns (bytes32) {\n FeatureUtils.validateFeature(dataStore, Keys.createShiftFeatureDisabledKey(address(this)));\n validateDataListLength(params.dataList.length);\n\n return ShiftUtils.createShift(\n dataStore,\n eventEmitter,\n shiftVault,\n account,\n srcChainId,\n params\n );\n }\n\n function cancelShift(bytes32 key) external override globalNonReentrant onlyController {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n Shift.Props memory shift = ShiftStoreUtils.get(_dataStore, key);\n\n FeatureUtils.validateFeature(_dataStore, Keys.cancelShiftFeatureDisabledKey(address(this)));\n\n validateRequestCancellation(\n shift.updatedAtTime(),\n \"Shift\"\n );\n\n ShiftUtils.cancelShift(\n _dataStore,\n eventEmitter,\n multichainVault,\n shiftVault,\n key,\n shift.account(),\n startingGas,\n Keys.USER_INITIATED_CANCEL,\n \"\"\n );\n }\n\n function executeShift(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external\n globalNonReentrant\n onlyOrderKeeper\n withOraclePrices(oracleParams)\n {\n uint256 startingGas = gasleft();\n\n Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);\n uint256 estimatedGasLimit = GasUtils.estimateExecuteShiftGasLimit(dataStore, shift);\n GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);\n\n try this._executeShift{ gas: executionGas }(\n key,\n shift,\n msg.sender\n ) {\n } catch (bytes memory reasonBytes) {\n _handleShiftError(\n key,\n startingGas,\n reasonBytes\n );\n }\n }\n\n function simulateExecuteShift(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params\n ) external\n override\n onlyController\n withSimulatedOraclePrices(params)\n globalNonReentrant\n {\n Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);\n\n this._executeShift(\n key,\n shift,\n msg.sender\n );\n }\n\n function _executeShift(\n bytes32 key,\n Shift.Props memory shift,\n address keeper\n ) external onlySelf {\n uint256 startingGas = gasleft();\n\n FeatureUtils.validateFeature(dataStore, Keys.executeShiftFeatureDisabledKey(address(this)));\n\n ShiftUtils.ExecuteShiftParams memory params = ShiftUtils.ExecuteShiftParams(\n dataStore,\n eventEmitter,\n multichainVault,\n shiftVault,\n oracle,\n depositHandler,\n withdrawalHandler,\n swapHandler,\n key,\n keeper,\n startingGas\n );\n\n ShiftUtils.executeShift(params, shift);\n }\n\n function _handleShiftError(\n bytes32 key,\n uint256 startingGas,\n bytes memory reasonBytes\n ) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n\n ShiftUtils.cancelShift(\n dataStore,\n eventEmitter,\n multichainVault,\n shiftVault,\n key,\n msg.sender,\n startingGas,\n reason,\n reasonBytes\n );\n }\n}\n" + }, + "contracts/exchange/WithdrawalHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./BaseHandler.sol\";\nimport \"../error/ErrorUtils.sol\";\n\nimport \"../market/Market.sol\";\n\nimport \"../withdrawal/Withdrawal.sol\";\nimport \"../withdrawal/WithdrawalVault.sol\";\nimport \"../withdrawal/WithdrawalStoreUtils.sol\";\nimport \"../withdrawal/WithdrawalUtils.sol\";\nimport \"../withdrawal/ExecuteWithdrawalUtils.sol\";\n\nimport \"./IWithdrawalHandler.sol\";\n\n// @title WithdrawalHandler\n// @dev Contract to handle creation, execution and cancellation of withdrawals\ncontract WithdrawalHandler is IWithdrawalHandler, BaseHandler, ReentrancyGuard {\n using Withdrawal for Withdrawal.Props;\n\n MultichainVault public immutable multichainVault;\n WithdrawalVault public immutable withdrawalVault;\n IMultichainTransferRouter public immutable multichainTransferRouter;\n ISwapHandler public immutable swapHandler;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n MultichainVault _multichainVault,\n IMultichainTransferRouter _multichainTransferRouter,\n WithdrawalVault _withdrawalVault,\n ISwapHandler _swapHandler\n ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {\n multichainVault = _multichainVault;\n multichainTransferRouter = _multichainTransferRouter;\n withdrawalVault = _withdrawalVault;\n swapHandler = _swapHandler;\n }\n\n // @dev creates a withdrawal in the withdrawal store\n // @param account the withdrawing account\n // @param srcChainId the source chain id\n // @param params IWithdrawalUtils.CreateWithdrawalParams\n function createWithdrawal(\n address account,\n uint256 srcChainId,\n IWithdrawalUtils.CreateWithdrawalParams calldata params\n ) external override globalNonReentrant onlyController returns (bytes32) {\n FeatureUtils.validateFeature(dataStore, Keys.createWithdrawalFeatureDisabledKey(address(this)));\n validateDataListLength(params.dataList.length);\n\n return WithdrawalUtils.createWithdrawal(\n dataStore,\n eventEmitter,\n withdrawalVault,\n account,\n srcChainId,\n params,\n false // isAtomicWithdrawal\n );\n }\n\n // @dev cancels a withdrawal\n // @param key the withdrawal key\n function cancelWithdrawal(bytes32 key) external override globalNonReentrant onlyController {\n uint256 startingGas = gasleft();\n\n DataStore _dataStore = dataStore;\n Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(_dataStore, key);\n\n FeatureUtils.validateFeature(_dataStore, Keys.cancelWithdrawalFeatureDisabledKey(address(this)));\n\n validateRequestCancellation(\n withdrawal.updatedAtTime(),\n \"Withdrawal\"\n );\n\n WithdrawalUtils.cancelWithdrawal(\n _dataStore,\n eventEmitter,\n multichainVault,\n withdrawalVault,\n key,\n withdrawal.account(),\n startingGas,\n Keys.USER_INITIATED_CANCEL,\n \"\"\n );\n }\n\n // @dev executes a withdrawal\n // @param key the key of the withdrawal to execute\n // @param oracleParams OracleUtils.SetPricesParams\n function executeWithdrawal(\n bytes32 key,\n OracleUtils.SetPricesParams calldata oracleParams\n )\n external\n globalNonReentrant\n onlyOrderKeeper\n withOraclePrices(oracleParams)\n {\n uint256 startingGas = gasleft();\n\n oracle.validateSequencerUp();\n\n Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);\n uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal);\n GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);\n\n uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);\n\n try this._executeWithdrawal{ gas: executionGas }(\n key,\n withdrawal,\n msg.sender,\n ISwapPricingUtils.SwapPricingType.Withdrawal\n ) {\n } catch (bytes memory reasonBytes) {\n _handleWithdrawalError(\n key,\n startingGas,\n reasonBytes\n );\n }\n }\n\n function executeWithdrawalFromController(\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams calldata executeWithdrawalParams,\n Withdrawal.Props calldata withdrawal\n ) external nonReentrant onlyController returns (IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory) {\n FeatureUtils.validateFeature(dataStore, Keys.executeWithdrawalFeatureDisabledKey(address(this)));\n return ExecuteWithdrawalUtils.executeWithdrawal(executeWithdrawalParams, withdrawal);\n }\n\n // @notice this function can only be called for markets where Chainlink\n // on-chain feeds are configured for all the tokens of the market\n // for example, if the market has index token as DOGE, long token as WETH\n // and short token as USDC, Chainlink on-chain feeds must be configured\n // for DOGE, WETH, USDC for this method to be callable for the market\n function executeAtomicWithdrawal(\n address account,\n IWithdrawalUtils.CreateWithdrawalParams calldata params,\n OracleUtils.SetPricesParams calldata oracleParams\n )\n external\n globalNonReentrant\n onlyController\n withOraclePricesForAtomicAction(oracleParams)\n {\n FeatureUtils.validateFeature(dataStore, Keys.executeAtomicWithdrawalFeatureDisabledKey(address(this)));\n validateDataListLength(params.dataList.length);\n\n if (\n params.addresses.longTokenSwapPath.length != 0 ||\n params.addresses.shortTokenSwapPath.length != 0\n ) {\n revert Errors.SwapsNotAllowedForAtomicWithdrawal(\n params.addresses.longTokenSwapPath.length,\n params.addresses.shortTokenSwapPath.length\n );\n }\n\n bytes32 key = WithdrawalUtils.createWithdrawal(\n dataStore,\n eventEmitter,\n withdrawalVault,\n account,\n 0, // srcChainId is the current block.chainId\n params,\n true // isAtomicWithdrawal\n );\n\n Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);\n\n this._executeWithdrawal(\n key,\n withdrawal,\n account,\n ISwapPricingUtils.SwapPricingType.AtomicWithdrawal\n );\n }\n\n // @dev simulate execution of a withdrawal to check for any errors\n // @param key the withdrawal key\n // @param params OracleUtils.SimulatePricesParams\n function simulateExecuteWithdrawal(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory params,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external\n override\n onlyController\n withSimulatedOraclePrices(params)\n globalNonReentrant\n {\n oracle.validateSequencerUp();\n\n Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);\n\n this._executeWithdrawal(\n key,\n withdrawal,\n msg.sender,\n swapPricingType\n );\n }\n\n // @dev executes a withdrawal\n // @param oracleParams OracleUtils.SetPricesParams\n // @param keeper the keeper executing the withdrawal\n // @param startingGas the starting gas\n function _executeWithdrawal(\n bytes32 key,\n Withdrawal.Props memory withdrawal,\n address keeper,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external onlySelf {\n uint256 startingGas = gasleft();\n\n FeatureUtils.validateFeature(dataStore, Keys.executeWithdrawalFeatureDisabledKey(address(this)));\n\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params = IExecuteWithdrawalUtils.ExecuteWithdrawalParams(\n dataStore,\n eventEmitter,\n multichainVault,\n multichainTransferRouter,\n withdrawalVault,\n oracle,\n swapHandler,\n key,\n keeper,\n startingGas,\n swapPricingType\n );\n\n ExecuteWithdrawalUtils.executeWithdrawal(params, withdrawal);\n }\n\n function _handleWithdrawalError(\n bytes32 key,\n uint256 startingGas,\n bytes memory reasonBytes\n ) internal {\n GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);\n\n bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);\n\n validateNonKeeperError(errorSelector, reasonBytes);\n\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n\n WithdrawalUtils.cancelWithdrawal(\n dataStore,\n eventEmitter,\n multichainVault,\n withdrawalVault,\n key,\n msg.sender,\n startingGas,\n reason,\n reasonBytes\n );\n }\n}\n" + }, + "contracts/external/ExternalHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./IExternalHandler.sol\";\nimport \"../error/Errors.sol\";\n\n// contracts with a CONTROLLER role or other roles may need to call external\n// contracts, since these roles may be able to directly change DataStore values\n// or perform other sensitive operations, these contracts should make these calls\n// through ExternalHandler instead\n//\n// note that anyone can make this contract call any function, this should be noted\n// to avoid assumptions of the contract's state in any protocol\n//\n// e.g. some tokens require the approved amount to be zero before the approved amount\n// can be changed, this should be taken into account if calling approve is required for\n// these tokens\ncontract ExternalHandler is IExternalHandler, ReentrancyGuard {\n using Address for address;\n using SafeERC20 for IERC20;\n\n // @notice refundTokens should be unique, this is because the refund loop\n // sends the full refund token balance on each iteration, so if there are\n // duplicate refund token addresses, then only the first refundReceiver\n // for that token would receive the tokens\n function makeExternalCalls(\n address[] memory targets,\n bytes[] memory dataList,\n address[] memory refundTokens,\n address[] memory refundReceivers\n ) external nonReentrant {\n if (targets.length != dataList.length) {\n revert Errors.InvalidExternalCallInput(targets.length, dataList.length);\n }\n\n if (refundTokens.length != refundReceivers.length) {\n revert Errors.InvalidExternalReceiversInput(refundTokens.length, refundReceivers.length);\n }\n\n for (uint256 i; i < targets.length; i++) {\n _makeExternalCall(\n targets[i],\n dataList[i]\n );\n }\n\n for (uint256 i; i < refundTokens.length; i++) {\n IERC20 refundToken = IERC20(refundTokens[i]);\n uint256 balance = refundToken.balanceOf(address(this));\n if (balance > 0) {\n refundToken.safeTransfer(refundReceivers[i], balance);\n }\n }\n }\n\n function _makeExternalCall(\n address target,\n bytes memory data\n ) internal {\n if (!target.isContract()) {\n revert Errors.InvalidExternalCallTarget(target);\n }\n\n (bool success, bytes memory returndata) = target.call(data);\n\n if (!success) {\n revert Errors.ExternalCallFailed(returndata);\n }\n }\n}\n" + }, + "contracts/external/IExternalHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IExternalHandler {\n function makeExternalCalls(\n address[] memory targets,\n bytes[] memory dataList,\n address[] memory refundTokens,\n address[] memory refundReceivers\n ) external;\n}\n" + }, + "contracts/feature/FeatureUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\n\n// @title FeatureUtils\n// @dev Library to validate if a feature is enabled or disabled\n// disabling a feature should only be used if it is absolutely necessary\n// disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders\n// could be disabled while liquidations may remain enabled\n// this could also occur if the chain is not producing blocks and lead to liquidatable positions\n// when block production resumes\n// the effects of disabling features should be carefully considered\nlibrary FeatureUtils {\n // @dev get whether a feature is disabled\n // @param dataStore DataStore\n // @param key the feature key\n // @return whether the feature is disabled\n function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {\n return dataStore.getBool(key);\n }\n\n // @dev validate whether a feature is enabled, reverts if the feature is disabled\n // @param dataStore DataStore\n // @param key the feature key\n function validateFeature(DataStore dataStore, bytes32 key) internal view {\n if (isFeatureDisabled(dataStore, key)) {\n revert Errors.DisabledFeature(key);\n }\n }\n}\n" + }, + "contracts/fee/FeeBatch.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title FeeBatch\n// @dev Struct for fee batches\nlibrary FeeBatch {\n struct Props {\n address[] feeTokens;\n uint256[] feeAmounts;\n uint256[] remainingAmounts;\n uint256 createdAt;\n }\n}\n" + }, + "contracts/fee/FeeBatchStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./FeeBatch.sol\";\n\n/**\n * @title FeeBatchStoreUtils\n * @dev Library for fee batch storage functions\n */\nlibrary FeeBatchStoreUtils {\n using FeeBatch for FeeBatch.Props;\n\n bytes32 public constant FEE_TOKENS = keccak256(abi.encode(\"FEE_TOKENS\"));\n bytes32 public constant FEE_AMOUNTS = keccak256(abi.encode(\"FEE_AMOUNTS\"));\n bytes32 public constant REMAINING_AMOUNTS = keccak256(abi.encode(\"REMAINING_AMOUNTS\"));\n bytes32 public constant CREATED_AT = keccak256(abi.encode(\"CREATED_AT\"));\n\n function get(DataStore dataStore, bytes32 key) public view returns (FeeBatch.Props memory) {\n FeeBatch.Props memory feeBatch;\n if (!dataStore.containsBytes32(Keys.FEE_BATCH_LIST, key)) {\n return feeBatch;\n }\n\n feeBatch.feeTokens = dataStore.getAddressArray(\n keccak256(abi.encode(key, FEE_TOKENS))\n );\n\n feeBatch.feeAmounts = dataStore.getUintArray(\n keccak256(abi.encode(key, FEE_AMOUNTS))\n );\n\n feeBatch.remainingAmounts = dataStore.getUintArray(\n keccak256(abi.encode(key, REMAINING_AMOUNTS))\n );\n\n feeBatch.createdAt = dataStore.getUint(\n keccak256(abi.encode(key, CREATED_AT))\n );\n\n return feeBatch;\n }\n\n function set(DataStore dataStore, bytes32 key, FeeBatch.Props memory feeBatch) external {\n dataStore.addBytes32(\n Keys.FEE_BATCH_LIST,\n key\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, FEE_TOKENS)),\n feeBatch.feeTokens\n );\n\n dataStore.setUintArray(\n keccak256(abi.encode(key, FEE_AMOUNTS)),\n feeBatch.feeAmounts\n );\n\n dataStore.setUintArray(\n keccak256(abi.encode(key, REMAINING_AMOUNTS)),\n feeBatch.remainingAmounts\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CREATED_AT)),\n feeBatch.createdAt\n );\n }\n\n function remove(DataStore dataStore, bytes32 key) external {\n if (!dataStore.containsBytes32(Keys.FEE_BATCH_LIST, key)) {\n revert Errors.FeeBatchNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.FEE_BATCH_LIST,\n key\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, FEE_TOKENS))\n );\n\n dataStore.removeUintArray(\n keccak256(abi.encode(key, FEE_AMOUNTS))\n );\n\n dataStore.removeUintArray(\n keccak256(abi.encode(key, REMAINING_AMOUNTS))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CREATED_AT))\n );\n }\n\n function getFeeBatchCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getAddressCount(Keys.FEE_BATCH_LIST);\n }\n\n function getFeeBatchKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.FEE_BATCH_LIST, start, end);\n }\n}\n" + }, + "contracts/fee/FeeDistributor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@layerzerolabs/oft-evm/contracts/OFTCore.sol\";\n\nimport \"./FeeDistributorUtils.sol\";\nimport \"./FeeDistributorVault.sol\";\nimport \"./FeeHandler.sol\";\nimport \"../multichain/MultichainReader.sol\";\nimport \"../oracle/ChainlinkPriceFeedUtils.sol\";\nimport \"../claim/ClaimUtils.sol\";\nimport \"../v1/IRewardTrackerV1.sol\";\nimport \"../v1/IRewardDistributorV1.sol\";\nimport \"../v1/IVesterV1.sol\";\nimport \"../v1/IMintable.sol\";\n\ncontract FeeDistributor is ReentrancyGuard, RoleModule {\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // constant and immutable variables are internal to reduce the contract size\n bytes internal constant EMPTY_BYTES = \"\";\n\n bytes32 internal constant GMX = keccak256(abi.encode(\"GMX\"));\n bytes32 internal constant EXTENDED_GMX_TRACKER = keccak256(abi.encode(\"EXTENDED_GMX_TRACKER\"));\n bytes32 internal constant DATASTORE = keccak256(abi.encode(\"DATASTORE\"));\n bytes32 internal constant TREASURY = keccak256(abi.encode(\"TREASURY\"));\n bytes32 internal constant LAYERZERO_OFT = keccak256(abi.encode(\"LAYERZERO_OFT\"));\n bytes32 internal constant CHAINLINK = keccak256(abi.encode(\"CHAINLINK\"));\n bytes32 internal constant ESGMX_VESTER = keccak256(abi.encode(\"ESGMX_VESTER\"));\n\n FeeDistributorVault internal immutable feeDistributorVault;\n FeeHandler internal immutable feeHandler;\n DataStore internal immutable dataStore;\n EventEmitter internal immutable eventEmitter;\n MultichainReader internal immutable multichainReader;\n\n address internal immutable claimVault;\n address internal immutable gmx;\n address internal immutable esGmx;\n address internal immutable wnt;\n\n receive() external payable {}\n\n constructor(\n RoleStore _roleStore,\n FeeDistributorVault _feeDistributorVault,\n FeeHandler _feeHandler,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n MultichainReader _multichainReader,\n address _claimVault,\n address _gmx,\n address _esGmx,\n address _wnt\n ) RoleModule(_roleStore) {\n feeDistributorVault = _feeDistributorVault;\n feeHandler = _feeHandler;\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n multichainReader = _multichainReader;\n claimVault = _claimVault;\n gmx = _gmx;\n esGmx = _esGmx;\n wnt = _wnt;\n }\n\n // @dev initiate the weekly fee distribution process\n //\n // The fee distribution process relies on the premise that this function is executed synchronously\n // across all chains to which it is deployed and is executed for the same fee distribution period\n //\n // In cases in which a chain encounters downtime or a keeper experiences issues, a contingency\n // should be in place to ensure the fee distribution is completed without issues\n function initiateDistribute() external nonReentrant onlyFeeDistributionKeeper {\n // validate that the FEE_RECEIVER address stored in dataStore = FeeDistributorVault\n address feeReceiver = _getAddress(Keys.FEE_RECEIVER);\n if (feeReceiver != address(feeDistributorVault)) {\n revert Errors.InvalidFeeReceiver(feeReceiver);\n }\n\n // validate distribution state and that distribution is not yet completed for the current week\n _validateDistributionState(DistributionState.None);\n _validateDistributionNotCompleted();\n\n // reset referral rewards deposited for WNT and esGMX to 0 for the current week's distribution\n _setUint(Keys2.feeDistributorReferralRewardsDepositedKey(wnt), 0);\n _setUint(Keys2.feeDistributorReferralRewardsDepositedKey(esGmx), 0);\n\n // populate readRequestInputs and extraOptionsInputs param used for cross chain LZRead request\n uint256[] memory chainIds = FeeDistributorUtils.retrieveChainIds(dataStore);\n uint256 chainIdsLength = chainIds.length;\n MultichainReaderUtils.ReadRequestInputs[]\n memory readRequestInputs = new MultichainReaderUtils.ReadRequestInputs[]((chainIdsLength - 1) * 3);\n uint256 targetChainIndex;\n for (uint256 i; i < chainIdsLength; i++) {\n uint256 chainId = chainIds[i];\n address extendedGmxTracker = _getAddressInfoForChain(chainId, EXTENDED_GMX_TRACKER);\n\n if (chainId == block.chainid) {\n uint256 feeAmountGmxCurrentChain = _getUint(Keys.withdrawableBuybackTokenAmountKey(gmx)) +\n _getFeeDistributorVaultBalance(gmx);\n uint256 stakedGmx = IERC20(extendedGmxTracker).totalSupply();\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(chainId), feeAmountGmxCurrentChain);\n _setUint(Keys2.feeDistributorStakedGmxKey(chainId), stakedGmx);\n continue;\n }\n\n address gmxTargetChain = _getAddressInfoForChain(chainId, GMX);\n uint32 layerZeroChainId = uint32(_getUint(Keys2.feeDistributorLayerZeroChainIdKey(chainId)));\n uint256 readRequestIndex = targetChainIndex * 3;\n readRequestInputs[readRequestIndex] = _setReadRequestInput(\n layerZeroChainId,\n _getAddressInfoForChain(chainId, DATASTORE),\n abi.encodeWithSelector(\n DataStore.getUint.selector,\n Keys.withdrawableBuybackTokenAmountKey(gmxTargetChain)\n )\n );\n readRequestIndex++;\n\n readRequestInputs[readRequestIndex] = _setReadRequestInput(\n layerZeroChainId,\n gmxTargetChain,\n abi.encodeWithSelector(IERC20.balanceOf.selector, _getAddressInfoForChain(chainId, Keys.FEE_RECEIVER))\n );\n readRequestIndex++;\n\n readRequestInputs[readRequestIndex] = _setReadRequestInput(\n layerZeroChainId,\n extendedGmxTracker,\n abi.encodeWithSelector(IERC20.totalSupply.selector)\n );\n targetChainIndex++;\n }\n\n MultichainReaderUtils.ExtraOptionsInputs memory extraOptionsInputs;\n extraOptionsInputs.gasLimit = uint128(_getUint(Keys2.FEE_DISTRIBUTOR_GAS_LIMIT));\n extraOptionsInputs.returnDataSize = ((uint32(chainIdsLength) - 1) * 96) + 8;\n\n _setDistributionState(uint256(DistributionState.Initiated));\n\n // calculate native token fee required and execute multichainReader.sendReadRequests LZRead request\n MessagingFee memory messagingFee = multichainReader.quoteReadFee(readRequestInputs, extraOptionsInputs);\n multichainReader.sendReadRequests{ value: messagingFee.nativeFee }(readRequestInputs, extraOptionsInputs);\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"numberOfChainsReadRequests\", chainIdsLength - 1);\n _setUintItem(eventData, 1, \"messagingFee.nativeFee\", messagingFee.nativeFee);\n _emitFeeDistributionEvent(eventData, \"FeeDistributionInitiated\");\n }\n\n // @dev receive and process the LZRead request received data and bridge GMX to other chains if necessary\n // @param guid unused parameter that represents the unique idenfifier for the LZRead request\n // @param receivedData MultichainReaderUtils.ReceivedData the LZRead request received data\n function processLzReceive(\n bytes32 /*guid*/,\n MultichainReaderUtils.ReceivedData calldata receivedData\n ) external onlyMultichainReader {\n // validate the distribution state and that the LZRead response is within the acceptable time limit\n _validateDistributionState(DistributionState.Initiated);\n _validateReadResponseTimestamp(receivedData.timestamp);\n\n // withdraw any GMX fees remaining in the feeHandler\n feeHandler.withdrawFees(gmx);\n\n // set the current chain and LZRead response fee amounts, staked GMX amounts, timestamp and current chain WNT price\n uint256[] memory chainIds = FeeDistributorUtils.retrieveChainIds(dataStore);\n uint256[] memory feeAmountsGmx = _createUintArray(chainIds.length);\n uint256[] memory stakedAmountsGmx = _createUintArray(chainIds.length);\n uint256 feeAmountGmxCurrentChain = _getUint(Keys2.feeDistributorFeeAmountGmxKey(block.chainid));\n uint256 stakedGmxCurrentChain = _getUint(Keys2.feeDistributorStakedGmxKey(block.chainid));\n uint256 totalFeeAmountGmx;\n uint256 totalStakedGmx;\n uint256 currentChainIndex;\n uint256 targetChainIndex;\n for (uint256 i; i < chainIds.length; i++) {\n uint256 chainId = chainIds[i];\n\n if (chainId == block.chainid) {\n feeAmountsGmx[i] = feeAmountGmxCurrentChain;\n stakedAmountsGmx[i] = stakedGmxCurrentChain;\n totalFeeAmountGmx += feeAmountGmxCurrentChain;\n totalStakedGmx += stakedGmxCurrentChain;\n currentChainIndex = i;\n continue;\n }\n (uint256 feeAmountGmx, uint256 stakedGmx) = _decodeReadData(receivedData.readData, targetChainIndex);\n feeAmountsGmx[i] = feeAmountGmx;\n stakedAmountsGmx[i] = stakedGmx;\n totalFeeAmountGmx += feeAmountGmx;\n totalStakedGmx += stakedGmx;\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(chainId), feeAmountGmx);\n _setUint(Keys2.feeDistributorStakedGmxKey(chainId), stakedGmx);\n targetChainIndex++;\n }\n _setUint(Keys2.FEE_DISTRIBUTOR_TOTAL_FEE_AMOUNT_GMX, totalFeeAmountGmx);\n _setUint(Keys2.FEE_DISTRIBUTOR_TOTAL_STAKED_GMX, totalStakedGmx);\n _setUint(Keys2.FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP, receivedData.timestamp);\n _setTokenPrices();\n\n uint256 requiredGmxAmount = Precision.mulDiv(totalFeeAmountGmx, stakedGmxCurrentChain, totalStakedGmx);\n uint256 totalGmxBridgedOut;\n // validate that the this chain has sufficient GMX to distribute fees\n if (feeAmountGmxCurrentChain >= requiredGmxAmount) {\n // only attempt to bridge to other chains if this chain has a surplus of GMX\n if (feeAmountGmxCurrentChain > requiredGmxAmount) {\n // Call the internal bridging function\n totalGmxBridgedOut = _calculateAndBridgeGmx(\n chainIds,\n totalFeeAmountGmx,\n stakedAmountsGmx,\n totalStakedGmx,\n feeAmountsGmx,\n currentChainIndex\n );\n\n uint256 newFeeAmountGmxCurrentChain = feeAmountGmxCurrentChain - totalGmxBridgedOut;\n // validate that the amount bridged does not result in a GMX fee amount deficit on the current chain\n if (requiredGmxAmount > newFeeAmountGmxCurrentChain) {\n revert Errors.AttemptedBridgeAmountTooHigh(\n requiredGmxAmount,\n feeAmountGmxCurrentChain,\n totalGmxBridgedOut\n );\n }\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(block.chainid), newFeeAmountGmxCurrentChain);\n }\n _setDistributionState(uint256(DistributionState.BridgingCompleted));\n } else {\n _setDistributionState(uint256(DistributionState.ReadDataReceived));\n }\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"feeAmountGmxCurrentChain\", feeAmountGmxCurrentChain);\n _setUintItem(eventData, 1, \"totalGmxBridgedOut\", totalGmxBridgedOut);\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"receivedData\", abi.encode(receivedData));\n _emitFeeDistributionEvent(eventData, \"FeeDistributionDataReceived\");\n }\n\n // @dev function executed via an automated Gelato transaction when bridged GMX is received on this chain\n function bridgedGmxReceived() external nonReentrant onlyFeeDistributionKeeper {\n _validateDistributionState(DistributionState.ReadDataReceived);\n _validateReadResponseTimestamp(_getUint(Keys2.FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP));\n _validateDistributionNotCompleted();\n\n uint256 totalFeeAmountGmx = _getUint(Keys2.FEE_DISTRIBUTOR_TOTAL_FEE_AMOUNT_GMX);\n uint256 stakedGmxCurrentChain = _getUint(Keys2.feeDistributorStakedGmxKey(block.chainid));\n uint256 totalStakedGmx = _getUint(Keys2.FEE_DISTRIBUTOR_TOTAL_STAKED_GMX);\n uint256 requiredGmxAmount = Precision.mulDiv(totalFeeAmountGmx, stakedGmxCurrentChain, totalStakedGmx);\n uint256 origFeeAmountGmxCurrentChain = _getUint(Keys2.feeDistributorFeeAmountGmxKey(block.chainid));\n\n // the gross amount of GMX that should be received, before taking into account slippage\n uint256 grossGmxReceived = requiredGmxAmount - origFeeAmountGmxCurrentChain;\n // the slippage factor used when bridging to account for bridging fees and potential slippage\n uint256 slippageFactor = _getUint(Keys2.feeDistributorBridgeSlippageFactorKey(block.chainid));\n // calculate the minimum acceptable amount of bridged GMX received, taking into account allowed slippage\n uint256 minGmxReceived = Precision.applyFactor(grossGmxReceived, slippageFactor);\n // the minimum allowed GMX amount after bridging, taking into account slippage\n uint256 minRequiredGmxAmount = origFeeAmountGmxCurrentChain + minGmxReceived;\n // retrieve the current GMX available to distribute now that bridging has been completed\n uint256 feeAmountGmxCurrentChain = _getFeeDistributorVaultBalance(gmx);\n\n // if the calculated amount doesn't meet the min bridging requirement, revert\n if (feeAmountGmxCurrentChain < minRequiredGmxAmount) {\n revert Errors.BridgedAmountNotSufficient(minRequiredGmxAmount, feeAmountGmxCurrentChain);\n }\n\n // now that the GMX available to distribute has been validated, update in dataStore and update DistributionState\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(block.chainid), feeAmountGmxCurrentChain);\n _setDistributionState(uint256(DistributionState.BridgingCompleted));\n\n // infer the bridged GMX received - note that it is technically possible for this value to not match the actual\n // bridged GMX received if for example, GMX is sent to the FeeDistributorVault from another source or GMX fees\n // are withdrawn from the FeeHandler after processLzReceive() is executed but before this function is executed\n uint256 gmxReceived = feeAmountGmxCurrentChain - origFeeAmountGmxCurrentChain;\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"gmxReceived\", gmxReceived);\n _setUintItem(eventData, 1, \"feeAmountGmxCurrentChain\", feeAmountGmxCurrentChain);\n _emitFeeDistributionEvent(eventData, \"FeeDistributionBridgedGmxReceived\");\n }\n\n // @dev complete the fee distribution calculations, token transfers and if necessary bridge GMX cross-chain\n // @param wntReferralRewardsInUsd the total WNT referral rewards in USD\n // @param esGmxForReferralRewards the total esGMX to be distributed for referral rewards\n // @param feesV1Usd the total V1 fees in USD\n // @param feesV2Usd the total V2 fees in USD\n function distribute(\n uint256 wntReferralRewardsInUsd,\n uint256 esGmxForReferralRewards,\n uint256 feesV1Usd,\n uint256 feesV2Usd\n ) external nonReentrant onlyFeeDistributionKeeper {\n // validate that the TREASURY address stored in dataStore is not a zero address\n address treasuryAddress = _getAddressInfo(TREASURY);\n if (treasuryAddress == address(0)) {\n revert Errors.ZeroTreasuryAddress();\n }\n\n // validate the distribution states, LZRead response timestamp and distribution has not yet been completed\n _validateDistributionState(DistributionState.BridgingCompleted);\n _validateReadResponseTimestamp(_getUint(Keys2.FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP));\n _validateDistributionNotCompleted();\n\n // withdraw any WNT fees remaining in the feeHandler\n feeHandler.withdrawFees(wnt);\n\n // calculate WNT costs and transfer to appropriate addresses\n (\n uint256 wntForKeepers,\n uint256 wntForChainlink,\n uint256 wntForTreasury,\n uint256 wntForReferralRewards\n ) = _calculateAndTransferWntCosts(wntReferralRewardsInUsd, feesV1Usd, feesV2Usd);\n\n // set the total fees in USD and referral reward amounts\n _setUint(Keys2.feeDistributorFeeAmountUsdKey(1), feesV1Usd);\n _setUint(Keys2.feeDistributorFeeAmountUsdKey(2), feesV2Usd);\n _setUint(Keys2.feeDistributorReferralRewardsAmountKey(wnt), wntForReferralRewards);\n _setUint(Keys2.feeDistributorReferralRewardsAmountKey(esGmx), esGmxForReferralRewards);\n _setUint(Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_TIMESTAMP, block.timestamp);\n _setDistributionState(uint256(DistributionState.None));\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(7);\n _setUintItem(eventData, 0, \"feesV1Usd\", feesV1Usd);\n _setUintItem(eventData, 1, \"feesV2Usd\", feesV2Usd);\n _setUintItem(eventData, 2, \"wntForKeepers\", wntForKeepers);\n _setUintItem(eventData, 3, \"wntForChainlink\", wntForChainlink);\n _setUintItem(eventData, 4, \"wntForTreasury\", wntForTreasury);\n _setUintItem(eventData, 5, \"wntForReferralRewards\", wntForReferralRewards);\n _setUintItem(eventData, 6, \"esGmxForReferralRewards\", esGmxForReferralRewards);\n _emitFeeDistributionEvent(eventData, \"FeeDistributionCompleted\");\n }\n\n // @dev deposit the calculated referral rewards in the ClaimVault for the specified accounts\n // @param token the token in which the referral rewards will be sent\n // @param distributionId the distribution id\n // @param params array of referral rewards deposit parameters\n function depositReferralRewards(\n address token,\n uint256 distributionId,\n ClaimUtils.DepositParam[] calldata params\n ) external nonReentrant onlyFeeDistributionKeeper {\n // validate the distribution state and that the accounts and amounts arrays are valid lengths\n _validateDistributionState(DistributionState.None);\n\n uint256 tokensForReferralRewards = _getUint(Keys2.feeDistributorReferralRewardsAmountKey(token));\n uint256 cumulativeDepositAmount = _getUint(Keys2.feeDistributorReferralRewardsDepositedKey(token));\n if (token == esGmx) {\n // validate the esGMX amount is valid and that there are sufficient esGMX in the feeDistributorVault\n uint256 maxEsGmxReferralRewards = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_ESGMX_AMOUNT);\n if (tokensForReferralRewards > maxEsGmxReferralRewards) {\n revert Errors.MaxEsGmxReferralRewardsAmountExceeded(tokensForReferralRewards, maxEsGmxReferralRewards);\n }\n\n uint256 vaultEsGmxBalance = _getFeeDistributorVaultBalance(esGmx);\n uint256 esGmxToBeDeposited = tokensForReferralRewards - cumulativeDepositAmount;\n if (esGmxToBeDeposited > vaultEsGmxBalance) {\n IMintable(esGmx).mint(address(feeDistributorVault), esGmxToBeDeposited - vaultEsGmxBalance);\n }\n\n // update esGMX bonus reward amounts for each account in the vester contract\n for (uint256 i; i < params.length; i++) {\n ClaimUtils.DepositParam memory param = params[i];\n\n address vester = _getAddressInfo(ESGMX_VESTER);\n uint256 totalEsGmxRewards = IVester(vester).bonusRewards(param.account) + param.amount;\n IVester(vester).setBonusRewards(param.account, totalEsGmxRewards);\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"amount\", param.amount);\n _setUintItem(eventData, 1, \"totalEsGmxRewards\", totalEsGmxRewards);\n\n eventEmitter.emitEventLog1(\"TotalEsGmxRewardsIncreased\", Cast.toBytes32(param.account), eventData);\n }\n } else if (token != wnt) {\n revert Errors.InvalidReferralRewardToken(token);\n }\n\n uint256 totalTransferAmount = ClaimUtils.incrementClaims(\n dataStore,\n eventEmitter,\n token,\n distributionId,\n params\n );\n _transferOut(token, claimVault, totalTransferAmount);\n dataStore.incrementUint(Keys.totalClaimableFundsAmountKey(token), totalTransferAmount);\n\n ClaimUtils._validateTotalClaimableFundsAmount(dataStore, token, claimVault);\n\n // validate that the cumulative referral rewards deposited is not greater than the total calculated amount\n cumulativeDepositAmount += totalTransferAmount;\n if (cumulativeDepositAmount > tokensForReferralRewards) {\n revert Errors.MaxReferralRewardsExceeded(token, cumulativeDepositAmount, tokensForReferralRewards);\n }\n\n _setUint(Keys2.feeDistributorReferralRewardsDepositedKey(token), cumulativeDepositAmount);\n }\n\n function _calculateAndBridgeGmx(\n uint256[] memory chainIds,\n uint256 totalFeeAmountGmx,\n uint256[] memory stakedAmountsGmx,\n uint256 totalStakedGmx,\n uint256[] memory feeAmountsGmx,\n uint256 currentChainIndex\n ) internal returns (uint256) {\n uint256 chainIdsLength = chainIds.length;\n uint256[] memory target = new uint256[](chainIdsLength);\n for (uint256 i; i < chainIdsLength; i++) {\n target[i] = Precision.mulDiv(totalFeeAmountGmx, stakedAmountsGmx[i], totalStakedGmx);\n }\n\n Transfer[] memory transfer = FeeDistributorUtils.computeTransfers(feeAmountsGmx, target);\n\n uint256[] memory bridgingAmounts = _createUintArray(chainIdsLength);\n\n for (uint256 j; j < transfer.length; j++) {\n if (transfer[j].from == currentChainIndex) {\n bridgingAmounts[transfer[j].to] = transfer[j].amount;\n }\n }\n\n return _bridgeGmx(chainIds, bridgingAmounts);\n }\n\n function _bridgeGmx(uint256[] memory chainIds, uint256[] memory bridgingAmounts) internal returns (uint256) {\n // Execute bridging transactions from current chain\n OFTCore layerzeroOft = OFTCore(_getAddressInfo(LAYERZERO_OFT));\n uint256 decimalConversionRate = layerzeroOft.decimalConversionRate();\n uint256 totalGmxBridgedOut;\n for (uint256 i; i < chainIds.length; i++) {\n uint256 bridgingAmount = bridgingAmounts[i];\n if (bridgingAmount == 0) continue;\n\n uint256 sendAmount = _removeDust(bridgingAmount, decimalConversionRate);\n\n // Move GMX needed for bridging to this contract from FeeDistributorVault\n _transferOut(gmx, address(this), sendAmount);\n\n // If the Layerzero OFT contract on this chain requires GMX approval, approve the sendAmount\n if (layerzeroOft.approvalRequired()) {\n IERC20(gmx).approve(address(layerzeroOft), sendAmount);\n }\n\n // Prepare remaining params needed for the bridging transaction\n uint256 chainId = chainIds[i];\n uint32 layerzeroChainId = uint32(_getUint(Keys2.feeDistributorLayerZeroChainIdKey(chainId)));\n bytes32 to = Cast.toBytes32(_getAddressInfoForChain(chainId, Keys.FEE_RECEIVER));\n uint256 minAmountOut = _removeDust(\n Precision.applyFactor(sendAmount, _getUint(Keys2.feeDistributorBridgeSlippageFactorKey(chainId))),\n decimalConversionRate\n );\n SendParam memory sendParam = SendParam(\n layerzeroChainId,\n to,\n sendAmount,\n minAmountOut,\n EMPTY_BYTES,\n EMPTY_BYTES,\n EMPTY_BYTES\n );\n MessagingFee memory messagingFee = layerzeroOft.quoteSend(sendParam, false);\n\n // Make the bridge call to the OFT contract\n layerzeroOft.send{ value: messagingFee.nativeFee }(sendParam, messagingFee, address(feeDistributorVault));\n\n // Add to the total bridged out\n totalGmxBridgedOut += sendAmount;\n }\n\n return totalGmxBridgedOut;\n }\n\n function _calculateAndTransferWntCosts(\n uint256 wntReferralRewardsInUsd,\n uint256 feesV1Usd,\n uint256 feesV2Usd\n ) internal returns (uint256, uint256, uint256, uint256) {\n // the WNT fee amount related calculations\n uint256 totalWntBalance = _getFeeDistributorVaultBalance(wnt);\n\n // calculate the WNT that needs to be sent to each keeper\n (uint256 keeperCostsV1, uint256 keeperCostsV2) = FeeDistributorUtils.calculateKeeperCosts(dataStore);\n uint256 wntForKeepers = keeperCostsV1 + keeperCostsV2;\n\n // calculate the WNT for chainlink costs and amount of WNT to be sent to the treasury\n (uint256 wntForChainlink, uint256 wntForTreasury) = _calculateChainlinkAndTreasuryAmounts(\n totalWntBalance,\n feesV1Usd,\n feesV2Usd,\n keeperCostsV2\n );\n\n // validate wntReferralRewardsInUsd and calculate the referral rewards in WNT to be sent\n uint256 wntForReferralRewards = _calculateWntForReferralRewards(wntReferralRewardsInUsd, feesV1Usd);\n\n wntForTreasury = _finalizeWntForTreasury(\n totalWntBalance,\n keeperCostsV1,\n keeperCostsV2,\n wntForChainlink,\n wntForTreasury,\n wntForReferralRewards\n );\n\n _transferWntCosts(wntForKeepers, wntForChainlink, wntForTreasury);\n\n return (wntForKeepers, wntForChainlink, wntForTreasury, wntForReferralRewards);\n }\n\n function _finalizeWntForTreasury(\n uint256 totalWntBalance,\n uint256 keeperCostsV1,\n uint256 keeperCostsV2,\n uint256 wntForChainlink,\n uint256 wntForTreasury,\n uint256 wntForReferralRewards\n ) internal returns (uint256) {\n // calculate the remaining WNT for Treasury, validate the calculated amount and adjust if necessary\n uint256 wntBeforeV1KeeperCostsAndReferralRewards = totalWntBalance -\n keeperCostsV2 -\n wntForChainlink -\n wntForTreasury;\n\n uint256 keeperAndReferralCostsV1 = keeperCostsV1 + wntForReferralRewards;\n if (keeperAndReferralCostsV1 > wntBeforeV1KeeperCostsAndReferralRewards) {\n uint256 additionalWntForV1Costs = keeperAndReferralCostsV1 - wntBeforeV1KeeperCostsAndReferralRewards;\n if (additionalWntForV1Costs > wntForTreasury) {\n uint256 maxWntFromTreasury = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_WNT_AMOUNT_FROM_TREASURY);\n uint256 additionalWntFromTreasury = additionalWntForV1Costs - wntForTreasury;\n if (additionalWntFromTreasury > maxWntFromTreasury) {\n revert Errors.MaxWntFromTreasuryExceeded(maxWntFromTreasury, additionalWntFromTreasury);\n }\n IERC20(wnt).transferFrom(\n _getAddressInfo(TREASURY),\n address(feeDistributorVault),\n additionalWntFromTreasury\n );\n wntForTreasury = 0;\n } else {\n wntForTreasury -= additionalWntForV1Costs;\n }\n } else {\n uint256 remainingWntForTreasury = wntBeforeV1KeeperCostsAndReferralRewards - keeperAndReferralCostsV1;\n wntForTreasury += remainingWntForTreasury;\n }\n return wntForTreasury;\n }\n\n function _transferWntCosts(uint256 wntForKeepers, uint256 wntForChainlink, uint256 wntForTreasury) internal {\n // transfer the WNT that needs to be sent to each keeper\n address[] memory keepers = dataStore.getAddressArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n uint256[] memory keepersTargetBalance = dataStore.getUintArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n uint256 wntToKeepers;\n for (uint256 i; i < keepers.length; i++) {\n address keeper = keepers[i];\n uint256 keeperBalance = keeper.balance;\n uint256 keeperTargetBalance = keepersTargetBalance[i];\n if (keeperBalance < keeperTargetBalance) {\n uint256 wntToKeeper = keeperTargetBalance - keeperBalance;\n feeDistributorVault.transferOutNativeToken(keeper, wntToKeeper);\n wntToKeepers += wntToKeeper;\n }\n }\n if (wntForKeepers != wntToKeepers) {\n revert Errors.KeeperAmountMismatch(wntForKeepers, wntToKeepers);\n }\n\n // transfer the WNT for chainlink costs and WNT for the treasury\n _transferOut(wnt, _getAddressInfo(CHAINLINK), wntForChainlink);\n _transferOut(wnt, _getAddressInfo(TREASURY), wntForTreasury);\n\n // transfer gmx fees for the week and update the last distribution time and tokens per interval\n address extendedGmxTracker = _getAddressInfoForChain(block.chainid, EXTENDED_GMX_TRACKER);\n uint256 feeAmountGmx = _getUint(Keys2.feeDistributorFeeAmountGmxKey(block.chainid));\n address distributor = IRewardTracker(extendedGmxTracker).distributor();\n _transferOut(gmx, extendedGmxTracker, feeAmountGmx);\n IRewardDistributor(distributor).updateLastDistributionTime();\n IRewardDistributor(distributor).setTokensPerInterval(feeAmountGmx / 1 weeks);\n }\n\n function _setUint(bytes32 fullKey, uint256 value) internal {\n dataStore.setUint(fullKey, value);\n }\n\n function _setDistributionState(uint256 value) internal {\n _setUint(Keys2.FEE_DISTRIBUTOR_STATE, value);\n }\n\n function _transferOut(address token, address receiver, uint256 amount) internal {\n feeDistributorVault.transferOut(token, receiver, amount);\n }\n\n function _emitFeeDistributionEvent(\n EventUtils.EventLogData memory eventData,\n string memory eventDescription\n ) internal {\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"eventDescription\", eventDescription);\n eventEmitter.emitEventLog(\"FeeDistributionEvent\", eventData);\n }\n\n function _setTokenPrices() internal {\n _setUint(Keys2.FEE_DISTRIBUTOR_GMX_PRICE, _getOraclePrice(gmx));\n _setUint(Keys2.FEE_DISTRIBUTOR_WNT_PRICE, _getOraclePrice(wnt));\n }\n\n function _calculateChainlinkAndTreasuryAmounts(\n uint256 totalWntBalance,\n uint256 feesV1Usd,\n uint256 feesV2Usd,\n uint256 keeperCostsV2\n ) internal view returns (uint256, uint256) {\n uint256 feesV1UsdInWnt = Precision.applyFactor(feesV1Usd, _getUint(Keys2.FEE_DISTRIBUTOR_V1_FEES_WNT_FACTOR));\n uint256 feesV2UsdInWnt = Precision.applyFactor(feesV2Usd, _getUint(Keys2.FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR));\n uint256 chainlinkTreasuryWntAmount = Precision.mulDiv(\n totalWntBalance,\n feesV2UsdInWnt,\n feesV1UsdInWnt + feesV2UsdInWnt\n );\n uint256 wntForChainlink = Precision.applyFactor(\n chainlinkTreasuryWntAmount,\n _getUint(Keys2.FEE_DISTRIBUTOR_CHAINLINK_FACTOR)\n );\n uint256 wntForTreasury = chainlinkTreasuryWntAmount - wntForChainlink - keeperCostsV2;\n\n return (wntForChainlink, wntForTreasury);\n }\n\n function _calculateWntForReferralRewards(\n uint256 wntReferralRewardsInUsd,\n uint256 feesV1Usd\n ) internal view returns (uint256) {\n uint256 maxWntReferralRewardsInUsdAmount = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_AMOUNT);\n if (wntReferralRewardsInUsd > maxWntReferralRewardsInUsdAmount) {\n revert Errors.MaxWntReferralRewardsInUsdAmountExceeded(\n wntReferralRewardsInUsd,\n maxWntReferralRewardsInUsdAmount\n );\n }\n\n uint256 maxWntReferralRewardsInUsdFactor = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_FACTOR);\n uint256 maxWntReferralRewardsInUsd = Precision.applyFactor(feesV1Usd, maxWntReferralRewardsInUsdFactor);\n if (wntReferralRewardsInUsd > maxWntReferralRewardsInUsd) {\n revert Errors.MaxWntReferralRewardsInUsdExceeded(wntReferralRewardsInUsd, maxWntReferralRewardsInUsd);\n }\n\n uint256 scaledWntPrice = _getUint(Keys2.FEE_DISTRIBUTOR_WNT_PRICE) * Precision.FLOAT_PRECISION;\n uint256 wntForReferralRewards = Precision.toFactor(wntReferralRewardsInUsd, scaledWntPrice);\n\n return wntForReferralRewards;\n }\n\n function _getUint(bytes32 fullKey) internal view returns (uint256) {\n return dataStore.getUint(fullKey);\n }\n\n function _getAddress(bytes32 fullKey) internal view returns (address) {\n return dataStore.getAddress(fullKey);\n }\n\n function _getAddressInfo(bytes32 addressKey) internal view returns (address) {\n return _getAddress(Keys2.feeDistributorAddressInfoKey(addressKey));\n }\n\n function _getAddressInfoForChain(uint256 chainId, bytes32 addressKey) internal view returns (address) {\n return _getAddress(Keys2.feeDistributorAddressInfoForChainKey(chainId, addressKey));\n }\n\n function _getFeeDistributorVaultBalance(address token) internal view returns (uint256) {\n return IERC20(token).balanceOf(address(feeDistributorVault));\n }\n\n function _getOraclePrice(address token) internal view returns (uint256) {\n // ChainlinkPriceFeedProvider.getOraclePrice() is not used since the prices are for non-stablecoin tokens\n (bool hasPriceFeed, uint256 price) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\n\n if (!hasPriceFeed) {\n revert Errors.EmptyChainlinkPriceFeed(token);\n }\n\n return price;\n }\n\n function _validateReadResponseTimestamp(uint256 readResponseTimestamp) internal view {\n if (block.timestamp - readResponseTimestamp > _getUint(Keys2.FEE_DISTRIBUTOR_MAX_READ_RESPONSE_DELAY)) {\n revert Errors.OutdatedReadResponse(readResponseTimestamp);\n }\n }\n\n function _validateDistributionState(DistributionState allowedDistributionState) internal view {\n uint256 distributionStateUint = _getUint(Keys2.FEE_DISTRIBUTOR_STATE);\n if (allowedDistributionState != DistributionState(distributionStateUint)) {\n revert Errors.InvalidDistributionState(distributionStateUint);\n }\n }\n\n function _validateDistributionNotCompleted() internal view {\n uint256 dayOfWeek = ((block.timestamp / 1 days) + 4) % 7;\n uint256 daysSinceDistributionDay = (dayOfWeek + 7 - _getUint(Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_DAY)) % 7;\n uint256 midnightToday = block.timestamp - (block.timestamp % 1 days);\n uint256 startOfDistributionWeek = midnightToday - (daysSinceDistributionDay * 1 days);\n uint256 lastDistributionTime = _getUint(Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_TIMESTAMP);\n if (lastDistributionTime > startOfDistributionWeek) {\n revert Errors.FeeDistributionAlreadyCompleted(lastDistributionTime, startOfDistributionWeek);\n }\n }\n\n function _setReadRequestInput(\n uint32 chainId,\n address target,\n bytes memory callData\n ) internal pure returns (MultichainReaderUtils.ReadRequestInputs memory) {\n return MultichainReaderUtils.ReadRequestInputs(chainId, target, callData);\n }\n\n function _createUintArray(uint256 arrayLength) internal pure returns (uint256[] memory) {\n return new uint256[](arrayLength);\n }\n\n function _createAddressArray(uint256 arrayLength) internal pure returns (address[] memory) {\n return new address[](arrayLength);\n }\n\n function _decodeReadData(\n bytes calldata readData,\n uint256 targetChainIndex\n ) internal pure returns (uint256, uint256) {\n uint256 offset = targetChainIndex * 96;\n (uint256 feeAmountGmx1, uint256 feeAmountGmx2, uint256 stakedGmx) = abi.decode(\n readData[offset:(offset + 96)],\n (uint256, uint256, uint256)\n );\n uint256 feeAmount = feeAmountGmx1 + feeAmountGmx2;\n return (feeAmount, stakedGmx);\n }\n\n function _removeDust(uint256 amount, uint256 decimalConversionRate) internal pure returns (uint256) {\n return (amount / decimalConversionRate) * decimalConversionRate;\n }\n\n function _setUintItem(\n EventUtils.EventLogData memory eventData,\n uint256 itemNumber,\n string memory itemName,\n uint256 uintItem\n ) internal pure {\n eventData.uintItems.setItem(itemNumber, itemName, uintItem);\n }\n}\n" + }, + "contracts/fee/FeeDistributorUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys2.sol\";\nimport \"../error/Errors.sol\";\n\nenum DistributionState {\n None,\n Initiated,\n ReadDataReceived,\n BridgingCompleted\n}\n\nstruct Transfer {\n uint256 from;\n uint256 to;\n uint256 amount;\n}\n\n// @title FeeDistributorUtils\nlibrary FeeDistributorUtils {\n function calculateKeeperCosts(DataStore dataStore) external view returns (uint256, uint256) {\n address[] memory keepers = dataStore.getAddressArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n uint256[] memory keepersTargetBalance = dataStore.getUintArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n bool[] memory keepersV2 = dataStore.getBoolArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n if (keepers.length != keepersTargetBalance.length || keepers.length != keepersV2.length) {\n revert Errors.KeeperArrayLengthMismatch(keepers.length, keepersTargetBalance.length, keepersV2.length);\n }\n\n uint256 keeperCostsV1;\n uint256 keeperCostsV2;\n for (uint256 i; i < keepers.length; i++) {\n uint256 keeperTargetBalance = keepersTargetBalance[i];\n uint256 keeperBalance = keepers[i].balance;\n if (keeperTargetBalance > keeperBalance) {\n uint256 keeperCost = keeperTargetBalance - keeperBalance;\n if (!keepersV2[i]) {\n keeperCostsV1 += keeperCost;\n } else {\n keeperCostsV2 += keeperCost;\n }\n }\n }\n\n return (keeperCostsV1, keeperCostsV2);\n }\n \n function retrieveChainIds(DataStore dataStore) external view returns (uint256[] memory) {\n uint256[] memory chainIds = dataStore.getUintArray(Keys2.FEE_DISTRIBUTOR_CHAIN_ID);\n sort(chainIds, 0, int256(chainIds.length - 1));\n return chainIds;\n }\n\n function computeTransfers(\n uint256[] memory balances,\n uint256[] memory targetBalances\n ) external pure returns (Transfer[] memory) {\n uint256 n = balances.length;\n if (targetBalances.length != n) {\n revert Errors.BridgingBalanceArrayMismatch(n, targetBalances.length);\n }\n\n int256[] memory diff = new int256[](n);\n for (uint256 i; i < n; i++) {\n diff[i] = int256(targetBalances[i]) - int256(balances[i]);\n }\n\n Transfer[] memory transfers = new Transfer[](n * n); // max possible\n uint256 count = 0;\n\n for (uint256 i; i < n; i++) {\n if (diff[i] <= 0) continue;\n\n for (uint256 j; j < n && diff[i] > 0; j++) {\n if (diff[j] >= 0) continue;\n\n uint256 sendAmount = uint256(min(diff[i], -diff[j]));\n if (sendAmount > 0) {\n transfers[count++] = Transfer(j, i, sendAmount);\n diff[i] -= int256(sendAmount);\n diff[j] += int256(sendAmount);\n }\n }\n }\n\n // Trim output\n Transfer[] memory result = new Transfer[](count);\n for (uint256 i; i < count; i++) {\n result[i] = transfers[i];\n }\n\n return result;\n }\n\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n function sort(uint256[] memory chainIds, int256 left, int256 right) internal pure {\n int256 i = left;\n int256 j = right;\n uint256 pivot = chainIds[uint256(left + (right - left) / 2)];\n\n while (i <= j) {\n while (chainIds[uint256(i)] < pivot) i++;\n while (chainIds[uint256(j)] > pivot) j--;\n if (i <= j) {\n (chainIds[uint256(i)], chainIds[uint256(j)]) = (chainIds[uint256(j)], chainIds[uint256(i)]);\n i++;\n j--;\n }\n }\n if (left < j) sort(chainIds, left, j);\n if (i < right) sort(chainIds, i, right);\n }\n}\n" + }, + "contracts/fee/FeeDistributorVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/Bank.sol\";\n\ncontract FeeDistributorVault is Bank {\n constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}\n}\n" + }, + "contracts/fee/FeeHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../role/RoleModule.sol\";\nimport \"../oracle/OracleModule.sol\";\nimport \"../utils/BasicMulticall.sol\";\nimport \"../fee/FeeUtils.sol\";\nimport \"../v1/IVaultV1.sol\";\nimport \"../v1/IVaultGovV1.sol\";\n\n// @title FeeHandler\ncontract FeeHandler is ReentrancyGuard, RoleModule, OracleModule, BasicMulticall {\n using SafeERC20 for IERC20;\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n\n struct FeeAmounts {\n uint256 gmx;\n uint256 wnt;\n }\n\n uint256 public constant v1 = 1;\n uint256 public constant v2 = 2;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n IVaultV1 public immutable vaultV1;\n address public immutable gmx;\n\n constructor(\n RoleStore _roleStore,\n IOracle _oracle,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IVaultV1 _vaultV1,\n address _gmx\n ) RoleModule(_roleStore) OracleModule(_oracle) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n vaultV1 = _vaultV1;\n gmx = _gmx;\n }\n\n // @dev withdraw fees in buybackTokens from this contract\n // note that claimFees should be called to claim pending fees if needed\n // before calling this function\n // @param buybackToken the token for which to withdraw fees\n function withdrawFees(address buybackToken) external nonReentrant onlyFeeKeeper {\n _validateBuybackToken(_getBatchSize(buybackToken), buybackToken);\n\n address receiver = dataStore.getAddress(Keys.FEE_RECEIVER);\n\n uint256 amount = dataStore.getUint(Keys.withdrawableBuybackTokenAmountKey(buybackToken));\n dataStore.setUint(Keys.withdrawableBuybackTokenAmountKey(buybackToken), 0);\n\n IERC20(buybackToken).safeTransfer(receiver, amount);\n }\n\n // @dev claim fees in feeToken from the specified markets\n // @param market the market from which to claim fees\n // @param feeToken the fee tokens to claim from the market\n function claimFees(address market, address feeToken, uint256 version) external nonReentrant {\n uint256 feeAmount;\n if (version == v1) {\n uint256 balanceBefore = IERC20(feeToken).balanceOf(address(this));\n IVaultGovV1(vaultV1.gov()).withdrawFees(address(vaultV1), feeToken, address(this));\n uint256 balanceAfter = IERC20(feeToken).balanceOf(address(this));\n feeAmount = balanceAfter - balanceBefore;\n } else if (version == v2) {\n _validateMarket(market);\n feeAmount = FeeUtils.claimFees(dataStore, eventEmitter, market, feeToken, address(this));\n } else {\n revert Errors.InvalidVersion(version);\n }\n\n _incrementAvailableFeeAmounts(version, feeToken, feeAmount);\n }\n\n // @dev receive an amount in feeToken by depositing the batchSize amount of the buybackToken\n // @param feeToken the token to receive with the fee amount calculated via an oracle price\n // @param buybackToken the token to deposit in the amount of batchSize in return for fees\n // @param minOutputAmount the minimum amount of the feeToken that the caller will receive\n function buyback(\n address feeToken,\n address buybackToken,\n uint256 minOutputAmount,\n OracleUtils.SetPricesParams memory params\n ) external nonReentrant withOraclePrices(params) {\n if (feeToken == buybackToken) {\n revert Errors.BuybackAndFeeTokenAreEqual(feeToken, buybackToken);\n }\n\n uint256 batchSize = _getBatchSize(buybackToken);\n _validateBuybackToken(batchSize, buybackToken);\n\n uint256 availableFeeAmount = _getAvailableFeeAmount(feeToken, buybackToken);\n if (availableFeeAmount == 0) {\n revert Errors.AvailableFeeAmountIsZero(feeToken, buybackToken, availableFeeAmount);\n }\n\n uint256 maxFeeTokenAmount = _getMaxFeeTokenAmount(feeToken, buybackToken, batchSize);\n uint256 outputAmount = availableFeeAmount < maxFeeTokenAmount ? availableFeeAmount : maxFeeTokenAmount;\n\n if (outputAmount < minOutputAmount) {\n revert Errors.InsufficientBuybackOutputAmount(feeToken, buybackToken, outputAmount, minOutputAmount);\n }\n\n _buybackFees(feeToken, buybackToken, batchSize, outputAmount, availableFeeAmount);\n }\n\n // note that there should not be any duplicates in the markets array\n // otherwise the returned output amount would not be accurate\n function getOutputAmount(\n address[] calldata markets,\n address feeToken,\n address buybackToken,\n uint256 version,\n uint256 feeTokenPrice,\n uint256 buybackTokenPrice\n ) external view returns (uint256) {\n uint256 batchSize = _getBatchSize(buybackToken);\n _validateBuybackToken(batchSize, buybackToken);\n\n uint256 feeAmount;\n uint256 availableFeeAmount = _getAvailableFeeAmount(feeToken, buybackToken);\n FeeAmounts memory feeAmounts;\n\n for (uint256 i; i < markets.length; i++) {\n if (version == v1) {\n feeAmount = vaultV1.feeReserves(feeToken);\n } else if (version == v2) {\n address market = markets[i];\n _validateMarket(market);\n feeAmount = _getUint(Keys.claimableFeeAmountKey(market, feeToken));\n } else {\n revert Errors.InvalidVersion(version);\n }\n\n feeAmounts = _getFeeAmounts(version, feeAmount);\n feeAmount = buybackToken == gmx ? feeAmounts.gmx : feeAmounts.wnt;\n availableFeeAmount = availableFeeAmount + feeAmount;\n }\n\n uint256 maxFeeTokenAmount = _getMaxFeeTokenAmount(\n feeToken,\n buybackToken,\n batchSize,\n feeTokenPrice,\n buybackTokenPrice\n );\n\n if (availableFeeAmount > maxFeeTokenAmount) {\n return maxFeeTokenAmount;\n }\n\n return availableFeeAmount;\n }\n\n function _buybackFees(\n address feeToken,\n address buybackToken,\n uint256 batchSize,\n uint256 buybackAmount,\n uint256 availableFeeAmount\n ) internal {\n _incrementWithdrawableBuybackTokenAmount(buybackToken, batchSize);\n _setAvailableFeeAmount(feeToken, buybackToken, availableFeeAmount - buybackAmount);\n\n IERC20(buybackToken).safeTransferFrom(msg.sender, address(this), batchSize);\n IERC20(feeToken).safeTransfer(msg.sender, buybackAmount);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"feeToken\", feeToken);\n eventData.addressItems.setItem(1, \"buybackToken\", buybackToken);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"batchSize\", batchSize);\n eventData.uintItems.setItem(1, \"buybackAmount\", buybackAmount);\n eventData.uintItems.setItem(2, \"availableFeeAmount\", availableFeeAmount);\n\n eventEmitter.emitEventLog(\"BuybackFees\", eventData);\n }\n\n function _incrementWithdrawableBuybackTokenAmount(address buybackToken, uint256 amount) internal {\n uint256 withdrawableAmount = dataStore.getUint(Keys.withdrawableBuybackTokenAmountKey(buybackToken));\n dataStore.setUint(Keys.withdrawableBuybackTokenAmountKey(buybackToken), withdrawableAmount + amount);\n }\n\n function _incrementAvailableFeeAmounts(uint256 version, address feeToken, uint256 feeAmount) internal {\n address wnt = dataStore.getAddress(Keys.WNT);\n\n FeeAmounts memory feeAmounts = _getFeeAmounts(version, feeAmount);\n\n _incrementAvailableFeeAmount(feeToken, gmx, feeAmounts.gmx);\n _incrementAvailableFeeAmount(feeToken, wnt, feeAmounts.wnt);\n }\n\n function _incrementAvailableFeeAmount(address feeToken, address buybackToken, uint256 amount) internal {\n // if the feeToken is the same as the buybackToken then no buyback swap is needed\n // increase the withdrawable buyback token amount directly in this case\n if (feeToken == buybackToken) {\n _incrementWithdrawableBuybackTokenAmount(buybackToken, amount);\n } else {\n uint256 availableFeeAmount = _getAvailableFeeAmount(feeToken, buybackToken);\n _setAvailableFeeAmount(feeToken, buybackToken, availableFeeAmount + amount);\n }\n }\n\n function _setAvailableFeeAmount(address feeToken, address buybackToken, uint256 availableFeeAmount) internal {\n dataStore.setUint(Keys.buybackAvailableFeeAmountKey(feeToken, buybackToken), availableFeeAmount);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"feeToken\", feeToken);\n eventData.addressItems.setItem(1, \"buybackToken\", buybackToken);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"availableFeeAmount\", availableFeeAmount);\n\n eventEmitter.emitEventLog(\"SetAvailableFeeAmount\", eventData);\n }\n\n function _getAvailableFeeAmount(address feeToken, address buybackToken) internal view returns (uint256) {\n return _getUint(Keys.buybackAvailableFeeAmountKey(feeToken, buybackToken));\n }\n\n function _getFeeAmounts(uint256 version, uint256 feeAmount) internal view returns (FeeAmounts memory) {\n uint256 gmxFactor = _getUint(Keys.buybackGmxFactorKey(version));\n FeeAmounts memory feeAmounts;\n\n feeAmounts.gmx = Precision.applyFactor(feeAmount, gmxFactor);\n feeAmounts.wnt = feeAmount - feeAmounts.gmx;\n return feeAmounts;\n }\n\n function _getMaxFeeTokenAmount(\n address feeToken,\n address buybackToken,\n uint256 batchSize\n ) internal view returns (uint256) {\n uint256 priceTimestamp = oracle.minTimestamp();\n uint256 maxPriceAge = _getUint(Keys.BUYBACK_MAX_PRICE_AGE);\n uint256 currentTimestamp = Chain.currentTimestamp();\n if ((priceTimestamp + maxPriceAge) < currentTimestamp) {\n revert Errors.MaxBuybackPriceAgeExceeded(priceTimestamp, maxPriceAge, currentTimestamp);\n }\n\n uint256 feeTokenPrice = oracle.getPrimaryPrice(feeToken).max;\n uint256 buybackTokenPrice = oracle.getPrimaryPrice(buybackToken).min;\n\n return _getMaxFeeTokenAmount(\n feeToken,\n buybackToken,\n batchSize,\n feeTokenPrice,\n buybackTokenPrice\n );\n }\n\n function _getMaxFeeTokenAmount(\n address feeToken,\n address buybackToken,\n uint256 batchSize,\n uint256 feeTokenPrice,\n uint256 buybackTokenPrice\n ) internal view returns (uint256) {\n uint256 expectedFeeTokenAmount = Precision.mulDiv(batchSize, buybackTokenPrice, feeTokenPrice);\n uint256 maxPriceImpactFactor = _getUint(Keys.buybackMaxPriceImpactFactorKey(feeToken)) +\n _getUint(Keys.buybackMaxPriceImpactFactorKey(buybackToken));\n\n return Precision.applyFactor(expectedFeeTokenAmount, maxPriceImpactFactor + Precision.FLOAT_PRECISION);\n }\n\n function _getBatchSize(address buybackToken) internal view returns (uint256) {\n return _getUint(Keys.buybackBatchAmountKey(buybackToken));\n }\n\n function _getUint(bytes32 fullKey) internal view returns (uint256) {\n return dataStore.getUint(fullKey);\n }\n\n function _validateBuybackToken(uint256 batchSize, address buybackToken) internal pure {\n if (batchSize == 0) {\n revert Errors.InvalidBuybackToken(buybackToken);\n }\n }\n\n function _validateMarket(address market) internal pure {\n if (market == address(0)) {\n revert Errors.EmptyClaimFeesMarket();\n }\n }\n}\n" + }, + "contracts/fee/FeeSwapUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"../v1/IRouterV1.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../fee/FeeBatchStoreUtils.sol\";\nimport \"../market/Market.sol\";\nimport \"../router/IExchangeRouter.sol\";\nimport \"../swap/SwapUtils.sol\";\n\n// @title FeeSwapUtils\nlibrary FeeSwapUtils {\n function swapFeesUsingV1(\n DataStore dataStore,\n IRouterV1 routerV1,\n address bridgingToken,\n bytes32 feeBatchKey,\n uint256 tokenIndex,\n address[] memory path,\n uint256 swapAmount,\n uint256 minOut\n ) external {\n (FeeBatch.Props memory feeBatch, address tokenIn) = _getSwapValues(\n dataStore,\n feeBatchKey,\n tokenIndex,\n swapAmount\n );\n\n if (path[path.length - 1] != bridgingToken) {\n revert Errors.InvalidSwapPathForV1(path, bridgingToken);\n }\n\n feeBatch.remainingAmounts[tokenIndex] -= swapAmount;\n FeeBatchStoreUtils.set(dataStore, feeBatchKey, feeBatch);\n\n IERC20(tokenIn).approve(address(routerV1), swapAmount);\n routerV1.swap(path, swapAmount, minOut, address(this));\n }\n\n function swapFeesUsingV2(\n DataStore dataStore,\n address routerV2,\n IExchangeRouter exchangeRouterV2,\n address bridgingToken,\n bytes32 feeBatchKey,\n uint256 tokenIndex,\n address market,\n address[] memory swapPath,\n uint256 swapAmount,\n uint256 executionFee,\n uint256 minOut\n ) external {\n (FeeBatch.Props memory feeBatch, address tokenIn) = _getSwapValues(\n dataStore,\n feeBatchKey,\n tokenIndex,\n swapAmount\n );\n\n SwapUtils.validateSwapOutputToken(dataStore, swapPath, tokenIn, bridgingToken);\n\n IBaseOrderUtils.CreateOrderParams memory params = _getSwapOrderParamsV2(\n dataStore,\n market,\n tokenIn,\n swapPath,\n swapAmount,\n executionFee,\n minOut\n );\n\n feeBatch.remainingAmounts[tokenIndex] -= swapAmount;\n FeeBatchStoreUtils.set(dataStore, feeBatchKey, feeBatch);\n\n IERC20(tokenIn).approve(routerV2, swapAmount);\n bytes32 orderKey = exchangeRouterV2.createOrder{ value: msg.value }(params);\n dataStore.setBytes32(Keys.feeDistributorSwapFeeBatchKey(orderKey), feeBatchKey);\n dataStore.setUint(Keys.feeDistributorSwapTokenIndexKey(orderKey), tokenIndex);\n }\n\n function _getSwapValues(\n DataStore dataStore,\n bytes32 feeBatchKey,\n uint256 tokenIndex,\n uint256 swapAmount\n ) internal view returns (FeeBatch.Props memory, address) {\n FeeBatch.Props memory feeBatch = FeeBatchStoreUtils.get(dataStore, feeBatchKey);\n\n if (tokenIndex > feeBatch.feeTokens.length) {\n revert Errors.InvalidFeeBatchTokenIndex(tokenIndex, feeBatch.feeTokens.length);\n }\n\n address tokenIn = feeBatch.feeTokens[tokenIndex];\n uint256 remainingAmount = feeBatch.remainingAmounts[tokenIndex];\n if (swapAmount > remainingAmount) {\n revert Errors.InvalidAmountInForFeeBatch(swapAmount, remainingAmount);\n }\n\n return (feeBatch, tokenIn);\n }\n\n function _getSwapOrderParamsV2(\n DataStore dataStore,\n address market,\n address tokenIn,\n address[] memory swapPath,\n uint256 swapAmount,\n uint256 executionFee,\n uint256 minOut\n ) internal view returns (IBaseOrderUtils.CreateOrderParams memory) {\n IBaseOrderUtils.CreateOrderParamsAddresses memory addresses = IBaseOrderUtils.CreateOrderParamsAddresses(\n address(this), // receiver\n address(this), // cancellationReceiver\n address(this), // callbackContract\n address(0), // uiFeeReceiver\n market, // market\n tokenIn, // initialCollateralToken\n swapPath // swapPath\n );\n\n uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT);\n\n IBaseOrderUtils.CreateOrderParamsNumbers memory numbers = IBaseOrderUtils.CreateOrderParamsNumbers(\n 0, // sizeDeltaUsd\n swapAmount, // initialCollateralDeltaAmount\n 0, // triggerPrice\n 0, // acceptablePrice\n executionFee, // executionFee\n maxCallbackGasLimit, // callbackGasLimit\n minOut, // minOutputAmount\n 0 // validFromTime\n );\n\n IBaseOrderUtils.CreateOrderParams memory params = IBaseOrderUtils.CreateOrderParams(\n addresses, // addresses\n numbers, // numbers\n Order.OrderType.MarketSwap, // orderType\n Order.DecreasePositionSwapType.NoSwap, // decreasePositionSwapType\n false, // isLong\n false, // shouldUnwrapNativeToken\n false, // autoCancel\n bytes32(0), // referralCode\n new bytes32[](0) // dataList\n );\n\n return params;\n }\n}\n" + }, + "contracts/fee/FeeUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\nimport \"../utils/AccountUtils.sol\";\nimport \"../market/MarketUtils.sol\";\n\nimport \"../market/MarketToken.sol\";\n\n// @title FeeUtils\n// @dev Library for fee actions\nlibrary FeeUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // @dev increment the claimable fee amount\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to increment claimable fees for\n // @param token the fee token\n // @param delta the amount to increment\n // @param feeType the type of the fee\n function incrementClaimableFeeAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 delta,\n bytes32 feeType\n ) external {\n if (delta == 0) {\n return;\n }\n\n bytes32 key = Keys.claimableFeeAmountKey(market, token);\n\n uint256 nextValue = dataStore.incrementUint(\n key,\n delta\n );\n\n emitClaimableFeeAmountUpdated(\n eventEmitter,\n market,\n token,\n delta,\n nextValue,\n feeType\n );\n }\n\n function incrementClaimableUiFeeAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address uiFeeReceiver,\n address market,\n address token,\n uint256 delta,\n bytes32 feeType\n ) external {\n if (delta == 0) {\n return;\n }\n\n uint256 nextValue = dataStore.incrementUint(\n Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver),\n delta\n );\n\n uint256 nextPoolValue = dataStore.incrementUint(\n Keys.claimableUiFeeAmountKey(market, token),\n delta\n );\n\n emitClaimableUiFeeAmountUpdated(\n eventEmitter,\n uiFeeReceiver,\n market,\n token,\n delta,\n nextValue,\n nextPoolValue,\n feeType\n );\n }\n\n function batchClaimFundingFees(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address[] memory markets,\n address[] memory tokens,\n address receiver,\n address account\n ) external returns (uint256[] memory) {\n if (markets.length != tokens.length) {\n revert Errors.InvalidClaimFundingFeesInput(markets.length, tokens.length);\n }\n\n FeatureUtils.validateFeature(dataStore, Keys.claimFundingFeesFeatureDisabledKey(address(this)));\n\n AccountUtils.validateReceiver(receiver);\n\n uint256[] memory claimedAmounts = new uint256[](markets.length);\n\n for (uint256 i; i < markets.length; i++) {\n claimedAmounts[i] = MarketUtils.claimFundingFees(\n dataStore,\n eventEmitter,\n markets[i],\n tokens[i],\n account,\n receiver\n );\n }\n\n return claimedAmounts;\n }\n\n // @dev claim fees for the specified market\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to claim fees for\n // @param token the fee token\n // @param receiver the receiver of the claimed fees\n function claimFees(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n address receiver\n ) internal returns (uint256) {\n AccountUtils.validateReceiver(receiver);\n\n bytes32 key = Keys.claimableFeeAmountKey(market, token);\n\n uint256 feeAmount = dataStore.getUint(key);\n dataStore.setUint(key, 0);\n\n MarketToken(payable(market)).transferOut(\n token,\n receiver,\n feeAmount\n );\n\n MarketUtils.validateMarketTokenBalance(dataStore, market);\n\n emitFeesClaimed(\n eventEmitter,\n market,\n receiver,\n feeAmount\n );\n\n return feeAmount;\n }\n\n function batchClaimUiFees(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address[] memory markets,\n address[] memory tokens,\n address receiver,\n address uiFeeReceiver\n ) external returns (uint256[] memory) {\n if (markets.length != tokens.length) {\n revert Errors.InvalidClaimUiFeesInput(markets.length, tokens.length);\n }\n\n FeatureUtils.validateFeature(dataStore, Keys.claimUiFeesFeatureDisabledKey(address(this)));\n\n AccountUtils.validateReceiver(receiver);\n\n uint256[] memory claimedAmounts = new uint256[](markets.length);\n\n for (uint256 i; i < markets.length; i++) {\n claimedAmounts[i] = _claimUiFees(\n dataStore,\n eventEmitter,\n uiFeeReceiver,\n markets[i],\n tokens[i],\n receiver\n );\n }\n\n return claimedAmounts;\n }\n\n function _claimUiFees(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address uiFeeReceiver,\n address market,\n address token,\n address receiver\n ) private returns (uint256) {\n bytes32 key = Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver);\n\n uint256 feeAmount = dataStore.getUint(key);\n dataStore.setUint(key, 0);\n\n uint256 nextPoolValue = dataStore.decrementUint(\n Keys.claimableUiFeeAmountKey(market, token),\n feeAmount\n );\n\n MarketToken(payable(market)).transferOut(\n token,\n receiver,\n feeAmount\n );\n\n MarketUtils.validateMarketTokenBalance(dataStore, market);\n\n emitUiFeesClaimed(\n eventEmitter,\n uiFeeReceiver,\n market,\n receiver,\n feeAmount,\n nextPoolValue\n );\n\n return feeAmount;\n }\n\n function emitClaimableFeeAmountUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 delta,\n uint256 nextValue,\n bytes32 feeType\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"nextValue\", nextValue);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"feeType\", feeType);\n\n eventEmitter.emitEventLog2(\n \"ClaimableFeeAmountUpdated\",\n Cast.toBytes32(market),\n feeType,\n eventData\n );\n }\n\n function emitClaimableUiFeeAmountUpdated(\n EventEmitter eventEmitter,\n address uiFeeReceiver,\n address market,\n address token,\n uint256 delta,\n uint256 nextValue,\n uint256 nextPoolValue,\n bytes32 feeType\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"uiFeeReceiver\", uiFeeReceiver);\n eventData.addressItems.setItem(1, \"market\", market);\n eventData.addressItems.setItem(2, \"token\", token);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"nextValue\", nextValue);\n eventData.uintItems.setItem(2, \"nextPoolValue\", nextPoolValue);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"feeType\", feeType);\n\n eventEmitter.emitEventLog2(\n \"ClaimableUiFeeAmountUpdated\",\n Cast.toBytes32(market),\n feeType,\n eventData\n );\n }\n\n function emitFeesClaimed(\n EventEmitter eventEmitter,\n address market,\n address receiver,\n uint256 feeAmount\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"receiver\", receiver);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"feeAmount\", feeAmount);\n\n eventEmitter.emitEventLog1(\n \"FeesClaimed\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitUiFeesClaimed(\n EventEmitter eventEmitter,\n address uiFeeReceiver,\n address market,\n address receiver,\n uint256 feeAmount,\n uint256 nextPoolValue\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"uiFeeReceiver\", uiFeeReceiver);\n eventData.addressItems.setItem(1, \"market\", market);\n eventData.addressItems.setItem(2, \"receiver\", receiver);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"feeAmount\", feeAmount);\n eventData.uintItems.setItem(1, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog1(\n \"UiFeesClaimed\",\n Cast.toBytes32(market),\n eventData\n );\n }\n}\n" + }, + "contracts/gas/GasUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../callback/CallbackUtils.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../utils/Precision.sol\";\n\nimport \"../deposit/Deposit.sol\";\nimport \"../withdrawal/Withdrawal.sol\";\nimport \"../shift/Shift.sol\";\nimport \"../order/Order.sol\";\nimport \"../glv/glvWithdrawal/GlvWithdrawal.sol\";\n\nimport \"../bank/StrictBank.sol\";\nimport \"../multichain/MultichainUtils.sol\";\n\n// @title GasUtils\n// @dev Library for execution fee estimation and payments\nlibrary GasUtils {\n using SafeERC20 for IERC20;\n\n using Deposit for Deposit.Props;\n using Withdrawal for Withdrawal.Props;\n using Shift for Shift.Props;\n using Order for Order.Props;\n using GlvDeposit for GlvDeposit.Props;\n using GlvWithdrawal for GlvWithdrawal.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // @param keeper address of the keeper\n // @param amount the amount of execution fee received\n event KeeperExecutionFee(address keeper, uint256 amount);\n // @param user address of the user\n // @param amount the amount of execution fee refunded\n event UserRefundFee(address user, uint256 amount);\n\n function getMinHandleExecutionErrorGas(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS);\n }\n\n function getMinHandleExecutionErrorGasToForward(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD);\n }\n\n function getMinAdditionalGasForExecution(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getUint(Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION);\n }\n\n function getExecutionGas(DataStore dataStore, uint256 startingGas) external view returns (uint256) {\n uint256 minHandleExecutionErrorGasToForward = getMinHandleExecutionErrorGasToForward(dataStore);\n if (startingGas < minHandleExecutionErrorGasToForward) {\n revert Errors.InsufficientExecutionGasForErrorHandling(startingGas, minHandleExecutionErrorGasToForward);\n }\n\n return startingGas - minHandleExecutionErrorGasToForward;\n }\n\n function validateExecutionGas(DataStore dataStore, uint256 startingGas, uint256 estimatedGasLimit) external view {\n uint256 minAdditionalGasForExecution = getMinAdditionalGasForExecution(dataStore);\n if (startingGas < estimatedGasLimit + minAdditionalGasForExecution) {\n revert Errors.InsufficientExecutionGas(startingGas, estimatedGasLimit, minAdditionalGasForExecution);\n }\n }\n\n // a minimum amount of gas is required to be left for cancellation\n // to prevent potential blocking of cancellations by malicious contracts using e.g. large revert reasons\n //\n // during the estimateGas call by keepers, an insufficient amount of gas may be estimated\n // the amount estimated may be insufficient for execution but sufficient for cancellaton\n // this could lead to invalid cancellations due to insufficient gas used by keepers\n //\n // to help prevent this, out of gas errors are attempted to be caught and reverted for estimateGas calls\n //\n // a malicious user could cause the estimateGas call of a keeper to fail, in which case the keeper could\n // still attempt to execute the transaction with a reasonable gas limit\n function validateExecutionErrorGas(DataStore dataStore, bytes memory reasonBytes) external view {\n // skip the validation if the execution did not fail due to an out of gas error\n // also skip the validation if this is not invoked in an estimateGas call (tx.origin != address(0))\n if (reasonBytes.length != 0 || tx.origin != address(0)) {\n return;\n }\n\n uint256 gas = gasleft();\n uint256 minHandleExecutionErrorGas = getMinHandleExecutionErrorGas(dataStore);\n\n if (gas < minHandleExecutionErrorGas) {\n revert Errors.InsufficientHandleExecutionErrorGas(gas, minHandleExecutionErrorGas);\n }\n }\n\n struct PayExecutionFeeContracts {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n StrictBank bank;\n }\n\n struct PayExecutionFeeCache {\n uint256 gasUsed;\n uint256 executionFeeForKeeper;\n uint256 refundFeeAmount;\n bool refundWasSent;\n address wnt;\n }\n\n // @dev pay the keeper the execution fee and refund any excess amount\n //\n // @param contracts the contracts to use for fee payment\n // @param key the key of the request\n // @param callbackContract the callback contract to use\n // @param executionFee the executionFee amount\n // @param startingGas the starting gas\n // @param oraclePriceCount number of oracle prices\n // @param keeper the keeper to pay\n // @param refundReceiver the account that should receive any excess gas refunds\n // @param srcChainId the source chain id\n function payExecutionFee(\n PayExecutionFeeContracts memory contracts,\n bytes32 key,\n address callbackContract,\n uint256 executionFee,\n uint256 startingGas,\n uint256 oraclePriceCount,\n address keeper,\n address refundReceiver,\n uint256 srcChainId\n ) external returns (uint256) {\n if (executionFee == 0) {\n return 0;\n }\n\n PayExecutionFeeCache memory cache;\n\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n startingGas -= gasleft() / 63;\n cache.gasUsed = startingGas - gasleft();\n\n // each external call forwards 63/64 of the remaining gas\n cache.executionFeeForKeeper = adjustGasUsage(contracts.dataStore, cache.gasUsed, oraclePriceCount) * tx.gasprice;\n\n if (cache.executionFeeForKeeper > executionFee) {\n cache.executionFeeForKeeper = executionFee;\n }\n\n contracts.bank.transferOutNativeToken(keeper, cache.executionFeeForKeeper);\n\n emitKeeperExecutionFee(contracts.eventEmitter, keeper, cache.executionFeeForKeeper);\n\n cache.refundFeeAmount = executionFee - cache.executionFeeForKeeper;\n if (cache.refundFeeAmount == 0) {\n return 0;\n }\n\n cache.wnt = contracts.dataStore.getAddress(Keys.WNT);\n contracts.bank.transferOut(cache.wnt, address(this), cache.refundFeeAmount);\n\n IWNT(cache.wnt).withdraw(cache.refundFeeAmount);\n\n EventUtils.EventLogData memory eventData;\n\n cache.refundWasSent = CallbackUtils.refundExecutionFee(\n contracts.dataStore,\n key,\n callbackContract,\n cache.refundFeeAmount,\n eventData\n );\n\n if (cache.refundWasSent) {\n emitExecutionFeeRefundCallback(contracts.eventEmitter, callbackContract, cache.refundFeeAmount);\n return 0;\n } else {\n if (srcChainId == 0) {\n TokenUtils.sendNativeToken(contracts.dataStore, refundReceiver, cache.refundFeeAmount);\n } else {\n TokenUtils.depositAndSendWrappedNativeToken(contracts.dataStore, address(contracts.multichainVault), cache.refundFeeAmount);\n MultichainUtils.recordTransferIn(contracts.dataStore, contracts.eventEmitter, contracts.multichainVault, cache.wnt, refundReceiver, 0); // srcChainId is the current block.chainId\n }\n emitExecutionFeeRefund(contracts.eventEmitter, refundReceiver, cache.refundFeeAmount);\n return cache.refundFeeAmount;\n }\n }\n\n // @dev validate that the provided executionFee is sufficient based on the estimatedGasLimit\n // @param dataStore DataStore\n // @param estimatedGasLimit the estimated gas limit\n // @param executionFee the execution fee provided\n // @param oraclePriceCount\n function validateExecutionFee(\n DataStore dataStore,\n uint256 estimatedGasLimit,\n uint256 executionFee,\n uint256 oraclePriceCount\n ) internal view returns (uint256, uint256) {\n uint256 gasLimit = adjustGasLimitForEstimate(dataStore, estimatedGasLimit, oraclePriceCount);\n uint256 minExecutionFee = gasLimit * tx.gasprice;\n if (executionFee < minExecutionFee) {\n revert Errors.InsufficientExecutionFee(minExecutionFee, executionFee);\n }\n return (gasLimit, minExecutionFee);\n }\n\n // @dev validate that the provided executionFee is sufficient based on the estimatedGasLimit\n // @param dataStore DataStore\n // @param estimatedGasLimit the estimated gas limit\n // @param executionFee the execution fee provided\n // @param oraclePriceCount\n // @param shouldCapMaxExecutionFee whether to cap the max execution fee\n function validateAndCapExecutionFee(\n DataStore dataStore,\n uint256 estimatedGasLimit,\n uint256 executionFee,\n uint256 oraclePriceCount,\n bool shouldCapMaxExecutionFee\n ) internal view returns (uint256, uint256) {\n (uint256 gasLimit, uint256 minExecutionFee) = validateExecutionFee(\n dataStore,\n estimatedGasLimit,\n executionFee,\n oraclePriceCount\n );\n\n if (!shouldCapMaxExecutionFee) {\n return (executionFee, 0);\n }\n // a malicious subaccount could provide a large executionFee\n // and receive most of it as a refund sent to a callbackContract\n // capping the max execution fee by multiplier * gasLimit * basefee should limit the potential loss\n\n // this capping should be applied for subaccount orders with a callbackContract if execution fee is increased\n // i.e. there is no need to cap the max execution fee for previously created orders even if it's high because it has already been capped\n\n // some blockchains may not support EIP-1559 and will return 0 for block.basefee\n // also block.basefee is 0 inside eth_call and eth_estimateGas\n uint256 basefee = block.basefee != 0 ? block.basefee : tx.gasprice;\n\n uint256 maxExecutionFeeMultiplierFactor = dataStore.getUint(Keys.MAX_EXECUTION_FEE_MULTIPLIER_FACTOR);\n uint256 maxExecutionFee = Precision.applyFactor(gasLimit * basefee, maxExecutionFeeMultiplierFactor);\n\n if (maxExecutionFee < minExecutionFee) {\n revert Errors.InvalidExecutionFee(executionFee, minExecutionFee, maxExecutionFee);\n }\n\n if (executionFee <= maxExecutionFee) {\n return (executionFee, 0);\n }\n\n uint256 executionFeeDiff = executionFee - maxExecutionFee;\n return (maxExecutionFee, executionFeeDiff);\n }\n\n function transferExcessiveExecutionFee(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Bank bank,\n address account,\n uint256 executionFeeDiff\n ) external {\n address wnt = TokenUtils.wnt(dataStore);\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\n\n if (holdingAddress == address(0)) {\n revert Errors.EmptyHoldingAddress();\n }\n\n bank.transferOut(wnt, holdingAddress, executionFeeDiff);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"executionFeeDiff\", executionFeeDiff);\n\n eventEmitter.emitEventLog1(\"ExcessiveExecutionFee\", Cast.toBytes32(account), eventData);\n }\n\n // @dev adjust the gas usage to pay a small amount to keepers\n // @param dataStore DataStore\n // @param gasUsed the amount of gas used\n // @param oraclePriceCount number of oracle prices\n function adjustGasUsage(\n DataStore dataStore,\n uint256 gasUsed,\n uint256 oraclePriceCount\n ) internal view returns (uint256) {\n // gas measurements are done after the call to withOraclePrices\n // withOraclePrices may consume a significant amount of gas\n // the baseGasLimit used to calculate the execution cost\n // should be adjusted to account for this\n // additionally, a transaction could fail midway through an execution transaction\n // before being cancelled, the possibility of this additional gas cost should\n // be considered when setting the baseGasLimit\n uint256 baseGasLimit = dataStore.getUint(Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1);\n baseGasLimit += dataStore.getUint(Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE) * oraclePriceCount;\n // the gas cost is estimated based on the gasprice of the request txn\n // the actual cost may be higher if the gasprice is higher in the execution txn\n // the multiplierFactor should be adjusted to account for this\n uint256 multiplierFactor = dataStore.getUint(Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR);\n uint256 gasLimit = baseGasLimit + Precision.applyFactor(gasUsed, multiplierFactor);\n return gasLimit;\n }\n\n // @dev adjust the estimated gas limit to help ensure the execution fee is sufficient during\n // the actual execution\n // @param dataStore DataStore\n // @param estimatedGasLimit the estimated gas limit\n function adjustGasLimitForEstimate(\n DataStore dataStore,\n uint256 estimatedGasLimit,\n uint256 oraclePriceCount\n ) internal view returns (uint256) {\n uint256 baseGasLimit = dataStore.getUint(Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1);\n baseGasLimit += dataStore.getUint(Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE) * oraclePriceCount;\n uint256 multiplierFactor = dataStore.getUint(Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR);\n uint256 gasLimit = baseGasLimit + Precision.applyFactor(estimatedGasLimit, multiplierFactor);\n return gasLimit;\n }\n\n // @dev get estimated number of oracle prices for deposit\n // @param swapsCount number of swaps in the deposit\n function estimateDepositOraclePriceCount(uint256 swapsCount) internal pure returns (uint256) {\n return 3 + swapsCount;\n }\n\n // @dev get estimated number of oracle prices for withdrawal\n // @param swapsCount number of swaps in the withdrawal\n function estimateWithdrawalOraclePriceCount(uint256 swapsCount) external pure returns (uint256) {\n return 3 + swapsCount;\n }\n\n // @dev get estimated number of oracle prices for order\n // @param swapsCount number of swaps in the order\n function estimateOrderOraclePriceCount(uint256 swapsCount) external pure returns (uint256) {\n return 3 + swapsCount;\n }\n\n // @dev get estimated number of oracle prices for shift\n function estimateShiftOraclePriceCount() external pure returns (uint256) {\n // for single asset markets only 3 prices will be required\n // and keeper will slightly overpay\n // it should not be an issue because execution fee goes back to keeper\n return 4;\n }\n\n function estimateGlvDepositOraclePriceCount(\n uint256 marketCount,\n uint256 swapsCount\n ) external pure returns (uint256) {\n // for single asset markets oracle price count will be overestimated by 1\n // it should not be an issue for GLV with multiple markets\n // because relative difference would be insignificant\n return 2 + marketCount + swapsCount;\n }\n\n function estimateGlvWithdrawalOraclePriceCount(\n uint256 marketCount,\n uint256 swapsCount\n ) internal pure returns (uint256) {\n // for single asset markets oracle price count will be overestimated by 1\n // it should not be an issue for GLV with multiple markets\n // because relative difference would be insignificant\n return 2 + marketCount + swapsCount;\n }\n\n function estimateCreateDepositGasLimit(\n DataStore dataStore\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.CREATE_DEPOSIT_GAS_LIMIT);\n }\n\n function estimateExecuteDepositGasLimit(\n DataStore dataStore,\n Deposit.Props memory deposit\n ) internal view returns (uint256) {\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n uint256 swapCount = deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length;\n uint256 gasForSwaps = swapCount * gasPerSwap;\n\n return dataStore.getUint(Keys.depositGasLimitKey()) + deposit.callbackGasLimit() + gasForSwaps;\n }\n\n function estimateCreateWithdrawalGasLimit(\n DataStore dataStore\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.CREATE_WITHDRAWAL_GAS_LIMIT);\n }\n\n // @dev the estimated gas limit for withdrawals\n // @param dataStore DataStore\n // @param withdrawal the withdrawal to estimate the gas limit for\n function estimateExecuteWithdrawalGasLimit(\n DataStore dataStore,\n Withdrawal.Props memory withdrawal\n ) external view returns (uint256) {\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n uint256 swapCount = withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length;\n uint256 gasForSwaps = swapCount * gasPerSwap;\n\n return dataStore.getUint(Keys.withdrawalGasLimitKey()) + withdrawal.callbackGasLimit() + gasForSwaps;\n }\n\n // @dev the estimated gas limit for shifts\n // @param dataStore DataStore\n // @param shift the shift to estimate the gas limit for\n function estimateExecuteShiftGasLimit(\n DataStore dataStore,\n Shift.Props memory shift\n ) external view returns (uint256) {\n return dataStore.getUint(Keys.shiftGasLimitKey()) + shift.callbackGasLimit();\n }\n\n // @dev the estimated gas limit for orders\n // @param dataStore DataStore\n // @param order the order to estimate the gas limit for\n function estimateExecuteOrderGasLimit(\n DataStore dataStore,\n Order.Props memory order\n ) external view returns (uint256) {\n if (Order.isIncreaseOrder(order.orderType())) {\n return estimateExecuteIncreaseOrderGasLimit(dataStore, order);\n }\n\n if (Order.isDecreaseOrder(order.orderType())) {\n return estimateExecuteDecreaseOrderGasLimit(dataStore, order);\n }\n\n if (Order.isSwapOrder(order.orderType())) {\n return estimateExecuteSwapOrderGasLimit(dataStore, order);\n }\n\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\n }\n\n // @dev the estimated gas limit for increase orders\n // @param dataStore DataStore\n // @param order the order to estimate the gas limit for\n function estimateExecuteIncreaseOrderGasLimit(\n DataStore dataStore,\n Order.Props memory order\n ) internal view returns (uint256) {\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n return\n dataStore.getUint(Keys.increaseOrderGasLimitKey()) +\n gasPerSwap *\n order.swapPath().length +\n order.callbackGasLimit();\n }\n\n // @dev the estimated gas limit for decrease orders\n // @param dataStore DataStore\n // @param order the order to estimate the gas limit for\n function estimateExecuteDecreaseOrderGasLimit(\n DataStore dataStore,\n Order.Props memory order\n ) internal view returns (uint256) {\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n uint256 swapCount = order.swapPath().length;\n if (order.decreasePositionSwapType() != Order.DecreasePositionSwapType.NoSwap) {\n swapCount += 1;\n }\n\n return dataStore.getUint(Keys.decreaseOrderGasLimitKey()) + gasPerSwap * swapCount + order.callbackGasLimit();\n }\n\n // @dev the estimated gas limit for swap orders\n // @param dataStore DataStore\n // @param order the order to estimate the gas limit for\n function estimateExecuteSwapOrderGasLimit(\n DataStore dataStore,\n Order.Props memory order\n ) internal view returns (uint256) {\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n return\n dataStore.getUint(Keys.swapOrderGasLimitKey()) +\n gasPerSwap *\n order.swapPath().length +\n order.callbackGasLimit();\n }\n\n function estimateCreateGlvDepositGasLimit(\n DataStore dataStore\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.CREATE_GLV_DEPOSIT_GAS_LIMIT);\n }\n\n // @dev the estimated gas limit for glv deposits\n // @param dataStore DataStore\n // @param deposit the deposit to estimate the gas limit for\n function estimateExecuteGlvDepositGasLimit(\n DataStore dataStore,\n GlvDeposit.Props memory glvDeposit,\n uint256 marketCount\n ) external view returns (uint256) {\n // glv deposit execution gas consumption depends on the amount of markets\n uint256 gasPerGlvPerMarket = dataStore.getUint(Keys.glvPerMarketGasLimitKey());\n uint256 gasForGlvMarkets = gasPerGlvPerMarket * marketCount;\n uint256 glvDepositGasLimit = dataStore.getUint(Keys.glvDepositGasLimitKey());\n\n uint256 gasLimit = glvDepositGasLimit + glvDeposit.callbackGasLimit() + gasForGlvMarkets;\n\n if (glvDeposit.isMarketTokenDeposit()) {\n // user provided GM, no separate deposit will be created and executed in this case\n return gasLimit;\n }\n\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n uint256 swapCount = glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length;\n uint256 gasForSwaps = swapCount * gasPerSwap;\n\n return gasLimit + dataStore.getUint(Keys.depositGasLimitKey()) + gasForSwaps;\n }\n\n function estimateCreateGlvWithdrawalGasLimit(\n DataStore dataStore\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.CREATE_GLV_WITHDRAWAL_GAS_LIMIT);\n }\n\n // @dev the estimated gas limit for glv withdrawals\n // @param dataStore DataStore\n // @param withdrawal the withdrawal to estimate the gas limit for\n function estimateExecuteGlvWithdrawalGasLimit(\n DataStore dataStore,\n GlvWithdrawal.Props memory glvWithdrawal,\n uint256 marketCount\n ) internal view returns (uint256) {\n // glv withdrawal execution gas consumption depends on the amount of markets\n uint256 gasPerGlvPerMarket = dataStore.getUint(Keys.glvPerMarketGasLimitKey());\n uint256 gasForGlvMarkets = gasPerGlvPerMarket * marketCount;\n uint256 glvWithdrawalGasLimit = dataStore.getUint(Keys.glvWithdrawalGasLimitKey());\n\n uint256 gasLimit = glvWithdrawalGasLimit + glvWithdrawal.callbackGasLimit() + gasForGlvMarkets;\n\n uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());\n uint256 swapCount = glvWithdrawal.longTokenSwapPath().length + glvWithdrawal.shortTokenSwapPath().length;\n uint256 gasForSwaps = swapCount * gasPerSwap;\n\n return gasLimit + dataStore.getUint(Keys.withdrawalGasLimitKey()) + gasForSwaps;\n }\n\n function estimateExecuteGlvShiftGasLimit(DataStore dataStore) external view returns (uint256) {\n return dataStore.getUint(Keys.glvShiftGasLimitKey());\n }\n\n function estimateSetTraderReferralCodeGasLimit(\n DataStore dataStore\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.SET_TRADER_REFERRAL_CODE_GAS_LIMIT);\n }\n\n function emitKeeperExecutionFee(EventEmitter eventEmitter, address keeper, uint256 executionFeeAmount) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"keeper\", keeper);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"executionFeeAmount\", executionFeeAmount);\n\n eventEmitter.emitEventLog1(\"KeeperExecutionFee\", Cast.toBytes32(keeper), eventData);\n }\n\n function emitExecutionFeeRefund(EventEmitter eventEmitter, address receiver, uint256 refundFeeAmount) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"receiver\", receiver);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"refundFeeAmount\", refundFeeAmount);\n\n eventEmitter.emitEventLog1(\"ExecutionFeeRefund\", Cast.toBytes32(receiver), eventData);\n }\n\n function emitExecutionFeeRefundCallback(\n EventEmitter eventEmitter,\n address callbackContract,\n uint256 refundFeeAmount\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"callbackContract\", callbackContract);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"refundFeeAmount\", refundFeeAmount);\n\n eventEmitter.emitEventLog1(\"ExecutionFeeRefundCallback\", Cast.toBytes32(callbackContract), eventData);\n }\n\n function payGelatoRelayFee(\n DataStore dataStore,\n address wnt,\n uint256 startingGas,\n uint256 calldataLength,\n uint256 availableFeeAmount\n ) external returns (uint256) {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n startingGas -= gasleft() / 63;\n\n address relayFeeAddress = dataStore.getAddress(Keys.RELAY_FEE_ADDRESS);\n if (relayFeeAddress == address(0)) {\n revert Errors.EmptyRelayFeeAddress();\n }\n\n uint256 relayFeeMultiplierFactor = dataStore.getUint(Keys.GELATO_RELAY_FEE_MULTIPLIER_FACTOR);\n if (relayFeeMultiplierFactor == 0) {\n relayFeeMultiplierFactor = Precision.FLOAT_PRECISION;\n }\n\n // relayFeeBaseAmount should include:\n // - 21000 base gas\n // - GelatoRelay contract gas\n // - gas for 2 token transfers: to relay fee address and residual fee to the user\n // - any other fixed gas costs before gasleft() and after the relay fee is calculated\n uint256 relayFeeBaseAmount = dataStore.getUint(Keys.GELATO_RELAY_FEE_BASE_AMOUNT);\n\n // would be non-zero for Arbitrum only\n uint256 l1Fee = Chain.getCurrentTxL1GasFees();\n\n uint256 l2Fee = (relayFeeBaseAmount + _getCalldataGas(calldataLength) + startingGas - gasleft()) * tx.gasprice;\n\n uint256 relayFee = Precision.applyFactor(l1Fee + l2Fee, relayFeeMultiplierFactor);\n\n if (relayFee > availableFeeAmount) {\n revert Errors.InsufficientRelayFee(relayFee, availableFeeAmount);\n }\n\n IERC20(wnt).safeTransfer(relayFeeAddress, relayFee);\n\n return relayFee;\n }\n\n function _getCalldataGas(uint256 calldataLength) internal pure returns (uint256) {\n if (calldataLength > 50000) {\n // we use 10 gas cost per byte for simplicity\n // a malicious actor could send large calldata with non-zero bytes to force relay pay more\n // this is unlikely to happen because the malicious actor would have to pay for the rest and wouldn't extra any profit\n // but to reduce the risk we limit the calldata length\n revert Errors.RelayCalldataTooLong(calldataLength);\n }\n\n // zero byte in call data costs 4 gas, non-zero byte costs 16 gas\n // there are more zero bytes in transactions on average, we take 10 as a relatively safe estimate\n // GelatoRelay contract receives calldata with a Call with fields like to, gasLimit, data, etc.\n // the GMX contract receives only data.call\n // in practice call fields are small compared to the call.data, so we only use msg.data received by GMX contract for simplicity\n uint256 txCalldataGasUsed = calldataLength * 10;\n\n // calculate words, apply ceiling\n uint256 memoryWords = (calldataLength + 31) / 32;\n\n // GelatoRelay contract calls GMX contract, CALL's gas depends on the calldata length\n // approximate formula for CALL gas consumption (excluding fixed costs e.g. 700 gas for the CALL opcode):\n // memory_cost(n) = (n_words^2) / 512 + (3 * n_words)\n // memory_expansion_cost = memory_cost(new) - memory_cost(previous)\n // we assume that previous memory_cost is 0 for simplicity\n uint256 gmxCallGasUsed = memoryWords ** 2 / 512 + memoryWords * 3;\n\n return txCalldataGasUsed + gmxCallGasUsed;\n }\n}\n" + }, + "contracts/glv/Glv.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\nlibrary Glv {\n struct Props {\n address glvToken;\n address longToken;\n address shortToken;\n }\n}\n" + }, + "contracts/glv/glvDeposit/ExecuteGlvDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../deposit/ExecuteDepositUtils.sol\";\nimport \"../../nonce/NonceUtils.sol\";\n\nimport \"../GlvVault.sol\";\nimport \"../GlvUtils.sol\";\nimport \"./GlvDepositEventUtils.sol\";\nimport \"./GlvDepositStoreUtils.sol\";\nimport \"./GlvDepositCalc.sol\";\n\nlibrary ExecuteGlvDepositUtils {\n using GlvDeposit for GlvDeposit.Props;\n using Deposit for Deposit.Props;\n using SafeCast for int256;\n using EventUtils for EventUtils.UintItems;\n\n struct ExecuteGlvDepositParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n IMultichainTransferRouter multichainTransferRouter;\n GlvVault glvVault;\n IOracle oracle;\n ISwapHandler swapHandler;\n bytes32 key;\n uint256 startingGas;\n address keeper;\n }\n\n struct ExecuteGlvDepositCache {\n Market.Props market;\n MarketPoolValueInfo.Props marketPoolValueInfo;\n uint256 marketTokenSupply;\n uint256 receivedMarketTokens;\n uint256 mintAmount;\n uint256 marketCount;\n uint256 oraclePriceCount;\n uint256 glvValue;\n uint256 glvSupply;\n }\n\n function executeGlvDeposit(\n ExecuteGlvDepositParams memory params,\n GlvDeposit.Props memory glvDeposit\n ) external returns (uint256) {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n GlvDepositStoreUtils.remove(params.dataStore, params.key, glvDeposit.account());\n\n // should be called before any tokens are minted\n GlvDepositCalc.validateFirstGlvDeposit(params.dataStore, glvDeposit);\n\n ExecuteGlvDepositCache memory cache;\n\n cache.receivedMarketTokens = _processMarketDeposit(params, glvDeposit, params.glvVault);\n\n // glvValue should be calculated after funds are deposited into GM market\n // but before GLV syncs GM token balance for glvValue to account for\n // slightly increased GM market price because of paid fees\n cache.glvValue = GlvUtils.getGlvValue(\n params.dataStore,\n params.oracle,\n glvDeposit.glv(),\n true // maximize\n );\n GlvToken(payable(glvDeposit.glv())).syncTokenBalance(glvDeposit.market());\n\n cache.glvSupply = GlvToken(payable(glvDeposit.glv())).totalSupply();\n cache.mintAmount = GlvDepositCalc.getMintAmount(\n params.dataStore,\n params.oracle,\n glvDeposit,\n cache.receivedMarketTokens,\n cache.glvValue,\n cache.glvSupply\n );\n if (cache.mintAmount < glvDeposit.minGlvTokens()) {\n revert Errors.MinGlvTokens(cache.mintAmount, glvDeposit.minGlvTokens());\n }\n\n if (glvDeposit.srcChainId() == 0) {\n GlvToken(payable(glvDeposit.glv())).mint(glvDeposit.receiver(), cache.mintAmount);\n } else {\n GlvToken(payable(glvDeposit.glv())).mint(address(params.multichainVault), cache.mintAmount);\n MultichainUtils.recordTransferIn(params.dataStore, params.eventEmitter, params.multichainVault, glvDeposit.glv(), glvDeposit.receiver(), 0); // srcChainId is the current block.chainId\n }\n\n cache.market = MarketUtils.getEnabledMarket(params.dataStore, glvDeposit.market());\n cache.marketPoolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n cache.market,\n params.oracle.getPrimaryPrice(cache.market.indexToken),\n params.oracle.getPrimaryPrice(cache.market.longToken),\n params.oracle.getPrimaryPrice(cache.market.shortToken),\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n true // maximize\n );\n cache.marketTokenSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(glvDeposit.market())));\n\n GlvUtils.validateGlvMarketTokenBalance(\n params.dataStore,\n glvDeposit.glv(),\n cache.market,\n cache.marketPoolValueInfo.poolValue.toUint256(),\n cache.marketTokenSupply\n );\n\n GlvDepositEventUtils.emitGlvDepositExecuted(\n params.eventEmitter,\n params.key,\n glvDeposit.account(),\n cache.mintAmount\n );\n\n cache.glvValue = GlvUtils.getGlvValue(\n params.dataStore,\n params.oracle,\n glvDeposit.glv(),\n true // maximize\n );\n cache.glvSupply = GlvToken(payable(glvDeposit.glv())).totalSupply();\n GlvEventUtils.emitGlvValueUpdated(params.eventEmitter, glvDeposit.glv(), cache.glvValue, cache.glvSupply);\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"receivedGlvTokens\", cache.mintAmount);\n CallbackUtils.afterGlvDepositExecution(params.key, glvDeposit, eventData);\n\n // use glvDeposit.dataList to determine if the GLV tokens minted should be bridged out to src chain\n BridgeOutFromControllerUtils.bridgeOutFromController(\n params.eventEmitter,\n params.multichainTransferRouter,\n glvDeposit.account(),\n glvDeposit.receiver(),\n glvDeposit.srcChainId(),\n glvDeposit.glv(), // token\n cache.mintAmount, // amount\n glvDeposit.dataList()\n );\n\n cache.marketCount = GlvUtils.getGlvMarketCount(params.dataStore, glvDeposit.glv());\n cache.oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount(\n cache.marketCount,\n glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length\n );\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.glvVault\n ),\n params.key,\n glvDeposit.callbackContract(),\n glvDeposit.executionFee(),\n params.startingGas,\n cache.oraclePriceCount,\n params.keeper,\n glvDeposit.receiver(),\n glvDeposit.srcChainId()\n );\n\n return cache.mintAmount;\n }\n\n\n function _processMarketDeposit(\n ExecuteGlvDepositParams memory params,\n GlvDeposit.Props memory glvDeposit,\n GlvVault glvVault\n ) private returns (uint256) {\n if (glvDeposit.isMarketTokenDeposit()) {\n Market.Props memory market = MarketUtils.getEnabledMarket(params.dataStore, glvDeposit.market());\n\n MarketUtils.MarketPrices memory marketPrices = MarketUtils.MarketPrices(\n params.oracle.getPrimaryPrice(market.indexToken),\n params.oracle.getPrimaryPrice(market.longToken),\n params.oracle.getPrimaryPrice(market.shortToken)\n );\n MarketUtils.validateMaxPnl(\n params.dataStore,\n market,\n marketPrices,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS\n );\n\n // user deposited GM tokens\n glvVault.transferOut(glvDeposit.market(), glvDeposit.glv(), glvDeposit.marketTokenAmount());\n return glvDeposit.marketTokenAmount();\n }\n\n Deposit.Props memory deposit = Deposit.Props(\n Deposit.Addresses({\n account: glvDeposit.glv(),\n receiver: glvDeposit.glv(),\n callbackContract: address(0),\n uiFeeReceiver: glvDeposit.uiFeeReceiver(),\n market: glvDeposit.market(),\n initialLongToken: glvDeposit.initialLongToken(),\n initialShortToken: glvDeposit.initialShortToken(),\n longTokenSwapPath: glvDeposit.longTokenSwapPath(),\n shortTokenSwapPath: glvDeposit.shortTokenSwapPath()\n }),\n Deposit.Numbers({\n initialLongTokenAmount: glvDeposit.initialLongTokenAmount(),\n initialShortTokenAmount: glvDeposit.initialShortTokenAmount(),\n minMarketTokens: 0,\n updatedAtTime: glvDeposit.updatedAtTime(),\n executionFee: 0,\n callbackGasLimit: 0,\n srcChainId: 0 // srcChainId is the current block.chainId\n }),\n Deposit.Flags({shouldUnwrapNativeToken: false}),\n new bytes32[](0) // dataList\n );\n\n bytes32 depositKey = NonceUtils.getNextKey(params.dataStore);\n params.dataStore.addBytes32(Keys.DEPOSIT_LIST, depositKey);\n DepositEventUtils.emitDepositCreated(params.eventEmitter, depositKey, deposit, Deposit.DepositType.Glv);\n\n IExecuteDepositUtils.ExecuteDepositParams memory executeDepositParams = IExecuteDepositUtils.ExecuteDepositParams(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.multichainTransferRouter,\n DepositVault(payable(params.glvVault)),\n params.oracle,\n params.swapHandler,\n depositKey,\n params.keeper,\n params.startingGas,\n ISwapPricingUtils.SwapPricingType.Deposit,\n true // includeVirtualInventoryImpact\n );\n\n uint256 receivedMarketTokens = ExecuteDepositUtils.executeDeposit(executeDepositParams, deposit);\n return receivedMarketTokens;\n }\n}\n" + }, + "contracts/glv/glvDeposit/GlvDeposit.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title GlvDeposit\n// @dev Struct for GLV deposits\nlibrary GlvDeposit {\n // @dev there is a limit on the number of fields a struct can have when being passed\n // or returned as a memory variable which can cause \"Stack too deep\" errors\n // use sub-structs to avoid this issue\n // large number of fields my also cause incorrect display in Tenderly\n // @param addresses address values\n // @param numbers number values\n // @param flags boolean values\n // @param _dataList a list of bytes32 values that can be used for additional data\n struct Props {\n Addresses addresses;\n Numbers numbers;\n Flags flags;\n bytes32[] _dataList;\n }\n\n // @param account the account depositing liquidity\n // @param receiver the address to send the liquidity tokens to\n // @param callbackContract the callback contract\n // @param uiFeeReceiver the ui fee receiver\n // @param market the market to deposit to\n struct Addresses {\n address glv;\n address account;\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address initialLongToken;\n address initialShortToken;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n\n // @param marketTokenAmount the amount of market tokens to deposit\n // @param initialLongTokenAmount the amount of long tokens to deposit\n // @param initialShortTokenAmount the amount of short tokens to deposit\n // @param minGlvTokens the minimum acceptable number of Glv tokens\n // sending funds back to the user in case the deposit gets cancelled\n // @param executionFee the execution fee for keepers\n // @param callbackGasLimit the gas limit for the callbackContract\n // @param srcChainId the source chain id\n struct Numbers {\n uint256 marketTokenAmount;\n uint256 initialLongTokenAmount;\n uint256 initialShortTokenAmount;\n uint256 minGlvTokens;\n uint256 updatedAtTime;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 srcChainId;\n }\n\n // @param shouldUnwrapNativeToken whether to unwrap the native token when\n // @param isMarketTokenDeposit whether to deposit market tokens or long/short tokens\n struct Flags {\n bool shouldUnwrapNativeToken;\n bool isMarketTokenDeposit;\n }\n\n\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n function receiver(Props memory props) internal pure returns (address) {\n return props.addresses.receiver;\n }\n\n function setReceiver(Props memory props, address value) internal pure {\n props.addresses.receiver = value;\n }\n\n function callbackContract(Props memory props) internal pure returns (address) {\n return props.addresses.callbackContract;\n }\n\n function setCallbackContract(Props memory props, address value) internal pure {\n props.addresses.callbackContract = value;\n }\n\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.uiFeeReceiver;\n }\n\n function setUiFeeReceiver(Props memory props, address value) internal pure {\n props.addresses.uiFeeReceiver = value;\n }\n\n function glv(Props memory props) internal pure returns (address) {\n return props.addresses.glv;\n }\n\n function setGlv(Props memory props, address value) internal pure {\n props.addresses.glv = value;\n }\n\n function market(Props memory props) internal pure returns (address) {\n return props.addresses.market;\n }\n\n function setMarket(Props memory props, address value) internal pure {\n props.addresses.market = value;\n }\n\n function initialLongToken(Props memory props) internal pure returns (address) {\n return props.addresses.initialLongToken;\n }\n\n function setInitialLongToken(Props memory props, address value) internal pure {\n props.addresses.initialLongToken = value;\n }\n\n function initialShortToken(Props memory props) internal pure returns (address) {\n return props.addresses.initialShortToken;\n }\n\n function setInitialShortToken(Props memory props, address value) internal pure {\n props.addresses.initialShortToken = value;\n }\n\n function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.longTokenSwapPath;\n }\n\n function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.longTokenSwapPath = value;\n }\n\n function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.shortTokenSwapPath;\n }\n\n function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.shortTokenSwapPath = value;\n }\n\n function marketTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.marketTokenAmount;\n }\n\n function setMarketTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.marketTokenAmount = value;\n }\n\n function initialLongTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.initialLongTokenAmount;\n }\n\n function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.initialLongTokenAmount = value;\n }\n\n function initialShortTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.initialShortTokenAmount;\n }\n\n function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.initialShortTokenAmount = value;\n }\n\n function minGlvTokens(Props memory props) internal pure returns (uint256) {\n return props.numbers.minGlvTokens;\n }\n\n function setMinGlvTokens(Props memory props, uint256 value) internal pure {\n props.numbers.minGlvTokens = value;\n }\n\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n\n function executionFee(Props memory props) internal pure returns (uint256) {\n return props.numbers.executionFee;\n }\n\n function setExecutionFee(Props memory props, uint256 value) internal pure {\n props.numbers.executionFee = value;\n }\n\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\n return props.numbers.callbackGasLimit;\n }\n\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\n props.numbers.callbackGasLimit = value;\n }\n\n function srcChainId(Props memory props) internal pure returns (uint256) {\n return props.numbers.srcChainId;\n }\n\n function setSrcChainId(Props memory props, uint256 value) internal pure {\n props.numbers.srcChainId = value;\n }\n\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\n return props.flags.shouldUnwrapNativeToken;\n }\n\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\n props.flags.shouldUnwrapNativeToken = value;\n }\n\n function isMarketTokenDeposit(Props memory props) internal pure returns (bool) {\n return props.flags.isMarketTokenDeposit;\n }\n\n function setIsMarketTokenDeposit(Props memory props, bool value) internal pure {\n props.flags.isMarketTokenDeposit = value;\n }\n\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\n return props._dataList;\n }\n\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\n props._dataList = value;\n }\n}\n" + }, + "contracts/glv/glvDeposit/GlvDepositCalc.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./GlvDeposit.sol\";\nimport \"../GlvUtils.sol\";\n\nlibrary GlvDepositCalc {\n using GlvDeposit for GlvDeposit.Props;\n using SafeCast for int256;\n\n address public constant RECEIVER_FOR_FIRST_GLV_DEPOSIT = address(1);\n\n function validateFirstGlvDeposit(\n DataStore dataStore,\n GlvDeposit.Props memory glvDeposit\n ) external view {\n address glv = glvDeposit.glv();\n uint256 initialGlvTokenSupply = GlvToken(payable(glv)).totalSupply();\n\n // return if this is not the first glv deposit\n if (initialGlvTokenSupply != 0) {\n return;\n }\n\n uint256 minGlvTokens = dataStore.getUint(Keys.minGlvTokensForFirstGlvDepositKey(glv));\n\n // return if there is no minGlvTokens requirement\n if (minGlvTokens == 0) {\n return;\n }\n\n if (glvDeposit.receiver() != RECEIVER_FOR_FIRST_GLV_DEPOSIT) {\n revert Errors.InvalidReceiverForFirstGlvDeposit(glvDeposit.receiver(), RECEIVER_FOR_FIRST_GLV_DEPOSIT);\n }\n\n if (glvDeposit.minGlvTokens() < minGlvTokens) {\n revert Errors.InvalidMinGlvTokensForFirstGlvDeposit(glvDeposit.minGlvTokens(), minGlvTokens);\n }\n }\n\n function getMintAmount(\n DataStore dataStore,\n IOracle oracle,\n GlvDeposit.Props memory glvDeposit,\n uint256 receivedMarketTokens,\n uint256 glvValue,\n uint256 glvSupply\n ) external view returns (uint256) {\n Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, glvDeposit.market());\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n dataStore,\n market,\n oracle.getPrimaryPrice(market.indexToken),\n oracle.getPrimaryPrice(market.longToken),\n oracle.getPrimaryPrice(market.shortToken),\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n false // maximize\n );\n uint256 marketTokenSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));\n uint256 receivedMarketTokensUsd = MarketUtils.marketTokenAmountToUsd(\n receivedMarketTokens,\n poolValueInfo.poolValue.toUint256(),\n marketTokenSupply\n );\n return GlvUtils.usdToGlvTokenAmount(receivedMarketTokensUsd, glvValue, glvSupply);\n }\n}\n" + }, + "contracts/glv/glvDeposit/GlvDepositEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../event/EventEmitter.sol\";\nimport \"../../event/EventUtils.sol\";\nimport \"../../utils/Cast.sol\";\n\nimport \"./GlvDeposit.sol\";\n\nlibrary GlvDepositEventUtils {\n using GlvDeposit for GlvDeposit.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitGlvDepositCreated(\n EventEmitter eventEmitter,\n bytes32 key,\n GlvDeposit.Props memory glvDeposit\n ) external {\n EventUtils.EventLogData memory eventData = createEventData(glvDeposit);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog2(\n \"GlvDepositCreated\",\n key,\n Cast.toBytes32(glvDeposit.account()),\n eventData\n );\n }\n\n function emitGlvDepositExecuted(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n uint256 receivedGlvTokens\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"receivedGlvTokens\", receivedGlvTokens);\n\n eventEmitter.emitEventLog2(\n \"GlvDepositExecuted\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitGlvDepositCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\n \"GlvDepositCancelled\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function createEventData(GlvDeposit.Props memory glvDeposit) public pure\n returns (EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(8);\n eventData.addressItems.setItem(0, \"account\", glvDeposit.account());\n eventData.addressItems.setItem(1, \"receiver\", glvDeposit.receiver());\n eventData.addressItems.setItem(2, \"callbackContract\", glvDeposit.callbackContract());\n eventData.addressItems.setItem(3, \"market\", glvDeposit.market());\n eventData.addressItems.setItem(4, \"glv\", glvDeposit.glv());\n eventData.addressItems.setItem(5, \"initialLongToken\", glvDeposit.initialLongToken());\n eventData.addressItems.setItem(6, \"initialShortToken\", glvDeposit.initialShortToken());\n eventData.addressItems.setItem(7, \"uiFeeReceiver\", glvDeposit.uiFeeReceiver());\n\n eventData.addressItems.initArrayItems(2);\n eventData.addressItems.setItem(0, \"longTokenSwapPath\", glvDeposit.longTokenSwapPath());\n eventData.addressItems.setItem(1, \"shortTokenSwapPath\", glvDeposit.shortTokenSwapPath());\n\n eventData.uintItems.initItems(8);\n eventData.uintItems.setItem(0, \"initialLongTokenAmount\", glvDeposit.initialLongTokenAmount());\n eventData.uintItems.setItem(1, \"initialShortTokenAmount\", glvDeposit.initialShortTokenAmount());\n eventData.uintItems.setItem(2, \"minGlvTokens\", glvDeposit.minGlvTokens());\n eventData.uintItems.setItem(3, \"updatedAtTime\", glvDeposit.updatedAtTime());\n eventData.uintItems.setItem(4, \"executionFee\", glvDeposit.executionFee());\n eventData.uintItems.setItem(5, \"callbackGasLimit\", glvDeposit.callbackGasLimit());\n eventData.uintItems.setItem(6, \"marketTokenAmount\", glvDeposit.marketTokenAmount());\n eventData.uintItems.setItem(7, \"srcChainId\", glvDeposit.srcChainId());\n\n eventData.boolItems.initItems(2);\n eventData.boolItems.setItem(0, \"shouldUnwrapNativeToken\", glvDeposit.shouldUnwrapNativeToken());\n eventData.boolItems.setItem(1, \"isMarketTokenDeposit\", glvDeposit.isMarketTokenDeposit());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", glvDeposit.dataList());\n return eventData;\n }\n}\n" + }, + "contracts/glv/glvDeposit/GlvDepositStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../data/Keys.sol\";\nimport \"../../data/DataStore.sol\";\n\nimport \"./GlvDeposit.sol\";\n\n/**\n * @title GlvDepositStoreUtils\n * @dev Library for deposit storage functions\n */\nlibrary GlvDepositStoreUtils {\n using GlvDeposit for GlvDeposit.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant RECEIVER = keccak256(abi.encode(\"RECEIVER\"));\n bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode(\"CALLBACK_CONTRACT\"));\n bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode(\"UI_FEE_RECEIVER\"));\n bytes32 public constant GLV = keccak256(abi.encode(\"GLV\"));\n bytes32 public constant MARKET = keccak256(abi.encode(\"MARKET\"));\n bytes32 public constant INITIAL_LONG_TOKEN = keccak256(abi.encode(\"INITIAL_LONG_TOKEN\"));\n bytes32 public constant INITIAL_SHORT_TOKEN = keccak256(abi.encode(\"INITIAL_SHORT_TOKEN\"));\n bytes32 public constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode(\"LONG_TOKEN_SWAP_PATH\"));\n bytes32 public constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode(\"SHORT_TOKEN_SWAP_PATH\"));\n\n bytes32 public constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode(\"MARKET_TOKEN_AMOUNT\"));\n bytes32 public constant INITIAL_LONG_TOKEN_AMOUNT = keccak256(abi.encode(\"INITIAL_LONG_TOKEN_AMOUNT\"));\n bytes32 public constant INITIAL_SHORT_TOKEN_AMOUNT = keccak256(abi.encode(\"INITIAL_SHORT_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_GLV_TOKENS = keccak256(abi.encode(\"MIN_GLV_TOKENS\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n bytes32 public constant EXECUTION_FEE = keccak256(abi.encode(\"EXECUTION_FEE\"));\n bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"CALLBACK_GAS_LIMIT\"));\n\n bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode(\"SHOULD_UNWRAP_NATIVE_TOKEN\"));\n bytes32 public constant IS_MARKET_TOKEN_DEPOSIT = keccak256(abi.encode(\"IS_MARKET_TOKEN_DEPOSIT\"));\n\n bytes32 public constant DATA_LIST = keccak256(abi.encode(\"DATA_LIST\"));\n\n bytes32 public constant SRC_CHAIN_ID = keccak256(abi.encode(\"SRC_CHAIN_ID\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (GlvDeposit.Props memory) {\n GlvDeposit.Props memory glvDeposit;\n if (!dataStore.containsBytes32(Keys.GLV_DEPOSIT_LIST, key)) {\n return glvDeposit;\n }\n\n glvDeposit.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n glvDeposit.setReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, RECEIVER))\n ));\n\n glvDeposit.setCallbackContract(dataStore.getAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n ));\n\n glvDeposit.setUiFeeReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n ));\n\n glvDeposit.setGlv(dataStore.getAddress(\n keccak256(abi.encode(key, GLV))\n ));\n\n glvDeposit.setMarket(dataStore.getAddress(\n keccak256(abi.encode(key, MARKET))\n ));\n\n glvDeposit.setInitialLongToken(dataStore.getAddress(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN))\n ));\n\n glvDeposit.setInitialShortToken(dataStore.getAddress(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))\n ));\n\n glvDeposit.setLongTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n ));\n\n glvDeposit.setShortTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n ));\n\n glvDeposit.setMarketTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n ));\n\n glvDeposit.setInitialLongTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))\n ));\n\n glvDeposit.setInitialShortTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))\n ));\n\n glvDeposit.setMinGlvTokens(dataStore.getUint(\n keccak256(abi.encode(key, MIN_GLV_TOKENS))\n ));\n\n glvDeposit.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n glvDeposit.setExecutionFee(dataStore.getUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n ));\n\n glvDeposit.setCallbackGasLimit(dataStore.getUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n ));\n\n glvDeposit.setSrcChainId(dataStore.getUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n ));\n\n glvDeposit.setShouldUnwrapNativeToken(dataStore.getBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n ));\n\n glvDeposit.setIsMarketTokenDeposit(dataStore.getBool(\n keccak256(abi.encode(key, IS_MARKET_TOKEN_DEPOSIT))\n ));\n\n glvDeposit.setDataList(dataStore.getBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n ));\n\n return glvDeposit;\n }\n\n function set(DataStore dataStore, bytes32 key, GlvDeposit.Props memory glvDeposit) external {\n dataStore.addBytes32(\n Keys.GLV_DEPOSIT_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountGlvDepositListKey(glvDeposit.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n glvDeposit.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, RECEIVER)),\n glvDeposit.receiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT)),\n glvDeposit.callbackContract()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER)),\n glvDeposit.uiFeeReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, GLV)),\n glvDeposit.glv()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET)),\n glvDeposit.market()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN)),\n glvDeposit.initialLongToken()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)),\n glvDeposit.initialShortToken()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),\n glvDeposit.longTokenSwapPath()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),\n glvDeposit.shortTokenSwapPath()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),\n glvDeposit.marketTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)),\n glvDeposit.initialLongTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)),\n glvDeposit.initialShortTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_GLV_TOKENS)),\n glvDeposit.minGlvTokens()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n glvDeposit.updatedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, EXECUTION_FEE)),\n glvDeposit.executionFee()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),\n glvDeposit.callbackGasLimit()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID)),\n glvDeposit.srcChainId()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),\n glvDeposit.shouldUnwrapNativeToken()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, IS_MARKET_TOKEN_DEPOSIT)),\n glvDeposit.isMarketTokenDeposit()\n );\n\n dataStore.setBytes32Array(\n keccak256(abi.encode(key, DATA_LIST)),\n glvDeposit.dataList()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.GLV_DEPOSIT_LIST, key)) {\n revert Errors.GlvDepositNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.GLV_DEPOSIT_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountGlvDepositListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, GLV))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_GLV_TOKENS))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, IS_MARKET_TOKEN_DEPOSIT))\n );\n\n dataStore.removeBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n );\n }\n\n function getGlvDepositCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.GLV_DEPOSIT_LIST);\n }\n\n function getGlvDepositKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.GLV_DEPOSIT_LIST, start, end);\n }\n\n function getAccountGlvDepositCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountGlvDepositListKey(account));\n }\n\n function getAccountGlvDepositKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountGlvDepositListKey(account), start, end);\n }\n}\n" + }, + "contracts/glv/glvDeposit/GlvDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n\nimport \"../../nonce/NonceUtils.sol\";\nimport \"../../gas/GasUtils.sol\";\nimport \"../../multichain/MultichainVault.sol\";\n\nimport \"../GlvVault.sol\";\nimport \"../GlvUtils.sol\";\n\nimport \"./IGlvDepositUtils.sol\";\nimport \"./GlvDepositEventUtils.sol\";\nimport \"./GlvDepositStoreUtils.sol\";\n\nlibrary GlvDepositUtils {\n using GlvDeposit for GlvDeposit.Props;\n\n struct CreateGlvDepositCache {\n uint256 marketTokenAmount;\n uint256 initialLongTokenAmount;\n uint256 initialShortTokenAmount;\n }\n\n struct CancelGlvDepositParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n GlvVault glvVault;\n bytes32 key;\n address keeper;\n uint256 startingGas;\n string reason;\n bytes reasonBytes;\n }\n\n address public constant RECEIVER_FOR_FIRST_GLV_DEPOSIT = address(1);\n\n function createGlvDeposit(\n DataStore dataStore,\n EventEmitter eventEmitter,\n GlvVault glvVault,\n address account,\n uint256 srcChainId,\n IGlvDepositUtils.CreateGlvDepositParams memory params\n ) external returns (bytes32) {\n AccountUtils.validateAccount(account);\n GlvUtils.validateGlv(dataStore, params.addresses.glv);\n GlvUtils.validateGlvMarket(dataStore, params.addresses.glv, params.addresses.market, true);\n\n MarketUtils.validateEnabledMarket(dataStore, params.addresses.market);\n\n CreateGlvDepositCache memory cache;\n\n if (params.isMarketTokenDeposit) {\n // user deposited GM tokens\n if (params.addresses.initialLongToken != address(0)) {\n revert Errors.InvalidGlvDepositInitialLongToken(params.addresses.initialLongToken);\n }\n if (params.addresses.initialShortToken != address(0)) {\n revert Errors.InvalidGlvDepositInitialShortToken(params.addresses.initialShortToken);\n }\n if (params.addresses.longTokenSwapPath.length > 0 || params.addresses.shortTokenSwapPath.length > 0) {\n revert Errors.InvalidGlvDepositSwapPath(\n params.addresses.longTokenSwapPath.length,\n params.addresses.shortTokenSwapPath.length\n );\n }\n cache.marketTokenAmount = glvVault.recordTransferIn(params.addresses.market);\n\n if (cache.marketTokenAmount == 0) {\n revert Errors.EmptyGlvMarketAmount();\n }\n } else {\n MarketUtils.validateSwapPath(dataStore, params.addresses.longTokenSwapPath);\n MarketUtils.validateSwapPath(dataStore, params.addresses.shortTokenSwapPath);\n\n if (params.addresses.initialLongToken == address(0)) {\n revert Errors.InvalidGlvDepositInitialLongToken(params.addresses.initialLongToken);\n }\n if (params.addresses.initialShortToken == address(0)) {\n revert Errors.InvalidGlvDepositInitialShortToken(params.addresses.initialShortToken);\n }\n\n // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would\n // be non-zero, the initialShortTokenAmount would be zero\n cache.initialLongTokenAmount = glvVault.recordTransferIn(params.addresses.initialLongToken);\n if (params.addresses.initialShortToken != params.addresses.initialLongToken) {\n cache.initialShortTokenAmount = glvVault.recordTransferIn(params.addresses.initialShortToken);\n }\n }\n\n address wnt = TokenUtils.wnt(dataStore);\n if (params.addresses.initialLongToken == wnt) {\n if (cache.initialLongTokenAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(cache.initialLongTokenAmount, params.executionFee);\n }\n cache.initialLongTokenAmount -= params.executionFee;\n } else if (params.addresses.initialShortToken == wnt) {\n if (cache.initialShortTokenAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(cache.initialShortTokenAmount, params.executionFee);\n }\n cache.initialShortTokenAmount -= params.executionFee;\n } else {\n uint256 wntAmount = glvVault.recordTransferIn(wnt);\n if (wntAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);\n }\n\n params.executionFee = wntAmount;\n }\n\n if (!params.isMarketTokenDeposit && (cache.initialLongTokenAmount == 0 && cache.initialShortTokenAmount == 0)) {\n revert Errors.EmptyGlvDepositAmounts();\n }\n\n AccountUtils.validateReceiver(params.addresses.receiver);\n\n GlvDeposit.Props memory glvDeposit = GlvDeposit.Props(\n GlvDeposit.Addresses({\n account: account,\n glv: params.addresses.glv,\n receiver: params.addresses.receiver,\n callbackContract: params.addresses.callbackContract,\n uiFeeReceiver: params.addresses.uiFeeReceiver,\n market: params.addresses.market,\n initialLongToken: params.addresses.initialLongToken,\n initialShortToken: params.addresses.initialShortToken,\n longTokenSwapPath: params.addresses.longTokenSwapPath,\n shortTokenSwapPath: params.addresses.shortTokenSwapPath\n }),\n GlvDeposit.Numbers({\n marketTokenAmount: cache.marketTokenAmount,\n initialLongTokenAmount: cache.initialLongTokenAmount,\n initialShortTokenAmount: cache.initialShortTokenAmount,\n minGlvTokens: params.minGlvTokens,\n updatedAtTime: Chain.currentTimestamp(),\n executionFee: params.executionFee,\n callbackGasLimit: params.callbackGasLimit,\n srcChainId: srcChainId\n }),\n GlvDeposit.Flags({\n shouldUnwrapNativeToken: params.shouldUnwrapNativeToken,\n isMarketTokenDeposit: params.isMarketTokenDeposit\n }),\n params.dataList\n );\n\n CallbackUtils.validateCallbackGasLimit(dataStore, params.callbackGasLimit);\n\n uint256 marketCount = GlvUtils.getGlvMarketCount(dataStore, glvDeposit.glv());\n uint256 estimatedGasLimit = GasUtils.estimateExecuteGlvDepositGasLimit(dataStore, glvDeposit, marketCount);\n uint256 oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount(\n marketCount,\n params.addresses.longTokenSwapPath.length + params.addresses.shortTokenSwapPath.length\n );\n GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount);\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n\n GlvDepositStoreUtils.set(dataStore, key, glvDeposit);\n\n GlvDepositEventUtils.emitGlvDepositCreated(eventEmitter, key, glvDeposit);\n\n return key;\n }\n\n function cancelGlvDeposit(CancelGlvDepositParams memory params) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(params.dataStore, params.key);\n GlvDepositStoreUtils.remove(params.dataStore, params.key, glvDeposit.account());\n\n if (glvDeposit.isMarketTokenDeposit()) {\n // in this case marketTokenAmount > 0\n if (glvDeposit.srcChainId() == 0) {\n params.glvVault.transferOut(\n glvDeposit.market(),\n glvDeposit.account(),\n glvDeposit.marketTokenAmount(),\n glvDeposit.shouldUnwrapNativeToken()\n );\n } else {\n params.glvVault.transferOut(\n glvDeposit.market(),\n address(params.multichainVault),\n glvDeposit.marketTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n glvDeposit.market(),\n glvDeposit.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n } else {\n if (glvDeposit.initialLongTokenAmount() > 0) {\n if (glvDeposit.srcChainId() == 0) {\n params.glvVault.transferOut(\n glvDeposit.initialLongToken(),\n glvDeposit.account(),\n glvDeposit.initialLongTokenAmount(),\n glvDeposit.shouldUnwrapNativeToken()\n );\n } else {\n params.glvVault.transferOut(\n glvDeposit.initialLongToken(),\n address(params.multichainVault),\n glvDeposit.initialLongTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n glvDeposit.initialLongToken(),\n glvDeposit.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n }\n\n if (glvDeposit.initialShortTokenAmount() > 0) {\n if (glvDeposit.srcChainId() == 0) {\n params.glvVault.transferOut(\n glvDeposit.initialShortToken(),\n glvDeposit.account(),\n glvDeposit.initialShortTokenAmount(),\n glvDeposit.shouldUnwrapNativeToken()\n );\n } else {\n params.glvVault.transferOut(\n glvDeposit.initialShortToken(),\n address(params.multichainVault),\n glvDeposit.initialShortTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n glvDeposit.initialShortToken(),\n glvDeposit.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n }\n }\n\n GlvDepositEventUtils.emitGlvDepositCancelled(\n params.eventEmitter,\n params.key,\n glvDeposit.account(),\n params.reason,\n params.reasonBytes\n );\n\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterGlvDepositCancellation(params.key, glvDeposit, eventData);\n\n uint256 marketCount = GlvUtils.getGlvMarketCount(params.dataStore, glvDeposit.glv());\n uint256 oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount(\n marketCount,\n glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length\n );\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.glvVault\n ),\n params.key,\n glvDeposit.callbackContract(),\n glvDeposit.executionFee(),\n params.startingGas,\n oraclePriceCount,\n params.keeper,\n glvDeposit.receiver(),\n glvDeposit.srcChainId()\n );\n }\n}\n" + }, + "contracts/glv/glvDeposit/GlvTestUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n/* import \"../../deposit/ExecuteDepositUtils.sol\"; */\n\nimport \"../GlvVault.sol\";\nimport \"../GlvUtils.sol\";\nimport \"./GlvDepositEventUtils.sol\";\nimport \"./GlvDepositStoreUtils.sol\";\n\nlibrary GlvTestUtils {\n}\n" + }, + "contracts/glv/glvDeposit/IGlvDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IGlvDepositUtils {\n struct CreateGlvDepositParams {\n CreateGlvDepositParamsAddresses addresses;\n uint256 minGlvTokens;\n uint256 executionFee;\n uint256 callbackGasLimit;\n bool shouldUnwrapNativeToken;\n bool isMarketTokenDeposit;\n bytes32[] dataList;\n }\n\n struct CreateGlvDepositParamsAddresses {\n address glv;\n address market;\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address initialLongToken;\n address initialShortToken;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n}\n" + }, + "contracts/glv/GlvEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nlibrary GlvEventUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitGlvMarketAdded(EventEmitter eventEmitter, address glv, address market) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"glv\", glv);\n eventData.addressItems.setItem(1, \"market\", market);\n\n eventEmitter.emitEventLog2(\"GlvMarketAdded\", Cast.toBytes32(glv), Cast.toBytes32(market), eventData);\n }\n\n function emitGlvMarketRemoved(EventEmitter eventEmitter, address glv, address market) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"glv\", glv);\n eventData.addressItems.setItem(1, \"market\", market);\n\n eventEmitter.emitEventLog2(\"GlvMarketRemoved\", Cast.toBytes32(glv), Cast.toBytes32(market), eventData);\n }\n\n function emitGlvValueUpdated(EventEmitter eventEmitter, address glv, uint256 value, uint256 supply) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"glv\", glv);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"value\", value);\n eventData.uintItems.setItem(1, \"supply\", supply);\n\n eventEmitter.emitEventLog1(\"GlvValueUpdated\", Cast.toBytes32(glv), eventData);\n }\n}\n" + }, + "contracts/glv/GlvFactory.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./GlvToken.sol\";\nimport \"./Glv.sol\";\nimport \"./GlvStoreUtils.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/Cast.sol\";\n\n// @title GlvFactory\n// @dev Contract to create glv\ncontract GlvFactory is RoleModule {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(RoleStore _roleStore, DataStore _dataStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n function createGlv(\n address longToken,\n address shortToken,\n bytes32 glvType,\n string memory name,\n string memory symbol\n ) external onlyMarketKeeper returns (Glv.Props memory) {\n // not the same as length in characters\n if (bytes(symbol).length > 30) {\n revert Errors.GlvSymbolTooLong();\n }\n if (bytes(name).length > 100) {\n revert Errors.GlvNameTooLong();\n }\n\n bytes32 salt = keccak256(abi.encode(\"GMX_GLV\", longToken, shortToken, glvType));\n\n address existingGlvAddress = dataStore.getAddress(GlvStoreUtils.getGlvSaltHash(salt));\n if (existingGlvAddress != address(0)) {\n revert Errors.GlvAlreadyExists(glvType, existingGlvAddress);\n }\n\n GlvToken glvToken = new GlvToken{salt: salt}(roleStore, dataStore, name, symbol);\n\n Glv.Props memory glv = Glv.Props({glvToken: address(glvToken), longToken: longToken, shortToken: shortToken});\n\n GlvStoreUtils.set(dataStore, address(glvToken), salt, glv);\n\n emitGlvCreated(address(glvToken), salt, longToken, shortToken, glvType);\n\n return glv;\n }\n\n function emitGlvCreated(address glvAddress, bytes32 salt, address longToken, address shortToken, bytes32 glvType) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"glvToken\", glvAddress);\n eventData.addressItems.setItem(1, \"longToken\", longToken);\n eventData.addressItems.setItem(2, \"shortToken\", shortToken);\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"salt\", salt);\n eventData.bytes32Items.setItem(1, \"glvType\", glvType);\n\n eventEmitter.emitEventLog1(\"GlvCreated\", Cast.toBytes32(glvAddress), eventData);\n }\n}\n" + }, + "contracts/glv/glvShift/GlvShift.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nlibrary GlvShift {\n struct Props {\n Addresses addresses;\n Numbers numbers;\n }\n\n struct Addresses {\n address glv;\n address fromMarket;\n address toMarket;\n }\n\n struct Numbers {\n uint256 marketTokenAmount;\n uint256 minMarketTokens;\n uint256 updatedAtTime;\n }\n\n function glv(Props memory props) internal pure returns (address) {\n return props.addresses.glv;\n }\n\n function setGlv(Props memory props, address value) internal pure {\n props.addresses.glv = value;\n }\n\n function fromMarket(Props memory props) internal pure returns (address) {\n return props.addresses.fromMarket;\n }\n\n function setFromMarket(Props memory props, address value) internal pure {\n props.addresses.fromMarket = value;\n }\n\n function toMarket(Props memory props) internal pure returns (address) {\n return props.addresses.toMarket;\n }\n\n function setToMarket(Props memory props, address value) internal pure {\n props.addresses.toMarket = value;\n }\n\n function marketTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.marketTokenAmount;\n }\n\n function setMarketTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.marketTokenAmount = value;\n }\n\n function minMarketTokens(Props memory props) internal pure returns (uint256) {\n return props.numbers.minMarketTokens;\n }\n\n function setMinMarketTokens(Props memory props, uint256 value) internal pure {\n props.numbers.minMarketTokens = value;\n }\n\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n}\n" + }, + "contracts/glv/glvShift/GlvShiftEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../event/EventEmitter.sol\";\nimport \"../../event/EventUtils.sol\";\n\nimport \"./GlvShift.sol\";\n\nlibrary GlvShiftEventUtils {\n using GlvShift for GlvShift.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitGlvShiftCreated(EventEmitter eventEmitter, bytes32 key, GlvShift.Props memory glvShift) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"fromMarket\", glvShift.fromMarket());\n eventData.addressItems.setItem(1, \"toMarket\", glvShift.toMarket());\n eventData.addressItems.setItem(2, \"glv\", glvShift.glv());\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"marketTokenAmount\", glvShift.marketTokenAmount());\n eventData.uintItems.setItem(1, \"minMarketTokens\", glvShift.minMarketTokens());\n eventData.uintItems.setItem(2, \"updatedAtTime\", glvShift.updatedAtTime());\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog1(\"GlvShiftCreated\", key, eventData);\n }\n\n function emitGlvShiftExecuted(EventEmitter eventEmitter, bytes32 key, uint256 receivedMarketTokens) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"receivedMarketTokens\", receivedMarketTokens);\n\n eventEmitter.emitEventLog1(\"GlvShiftExecuted\", key, eventData);\n }\n\n function emitGlvShiftCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog1(\"GlvShiftCancelled\", key, eventData);\n }\n}\n" + }, + "contracts/glv/glvShift/GlvShiftStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../data/Keys.sol\";\nimport \"../../data/DataStore.sol\";\n\nimport \"./GlvShift.sol\";\n\nlibrary GlvShiftStoreUtils {\n using GlvShift for GlvShift.Props;\n\n bytes32 public constant GLV = keccak256(abi.encode(\"GLV\"));\n bytes32 public constant FROM_MARKET = keccak256(abi.encode(\"FROM_MARKET\"));\n bytes32 public constant TO_MARKET = keccak256(abi.encode(\"TO_MARKET\"));\n\n bytes32 public constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode(\"MARKET_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_MARKET_TOKENS = keccak256(abi.encode(\"MIN_MARKET_TOKENS\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (GlvShift.Props memory) {\n GlvShift.Props memory glvShift;\n if (!dataStore.containsBytes32(Keys.GLV_SHIFT_LIST, key)) {\n return glvShift;\n }\n\n glvShift.setGlv(dataStore.getAddress(\n keccak256(abi.encode(key, GLV))\n ));\n\n glvShift.setFromMarket(dataStore.getAddress(\n keccak256(abi.encode(key, FROM_MARKET))\n ));\n\n glvShift.setToMarket(dataStore.getAddress(\n keccak256(abi.encode(key, TO_MARKET))\n ));\n\n glvShift.setMarketTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n ));\n\n glvShift.setMinMarketTokens(dataStore.getUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS))\n ));\n\n glvShift.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n return glvShift;\n }\n\n function set(DataStore dataStore, bytes32 key, GlvShift.Props memory glvShift) external {\n dataStore.addBytes32(\n Keys.GLV_SHIFT_LIST,\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, GLV)),\n glvShift.glv()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, FROM_MARKET)),\n glvShift.fromMarket()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, TO_MARKET)),\n glvShift.toMarket()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),\n glvShift.marketTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS)),\n glvShift.minMarketTokens()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n glvShift.updatedAtTime()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key) external {\n if (!dataStore.containsBytes32(Keys.GLV_SHIFT_LIST, key)) {\n revert Errors.GlvShiftNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.GLV_SHIFT_LIST,\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, GLV))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, FROM_MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, TO_MARKET))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n }\n\n function getGlvShiftCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.GLV_SHIFT_LIST);\n }\n\n function getGlvShiftKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.GLV_SHIFT_LIST, start, end);\n }\n}\n" + }, + "contracts/glv/glvShift/GlvShiftUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../event/EventEmitter.sol\";\nimport \"../../multichain/MultichainVault.sol\";\nimport \"../../shift/ShiftUtils.sol\";\nimport \"../GlvUtils.sol\";\nimport \"../GlvVault.sol\";\n\nimport \"./GlvShiftStoreUtils.sol\";\nimport \"./GlvShiftEventUtils.sol\";\n\nlibrary GlvShiftUtils {\n using GlvShift for GlvShift.Props;\n using SafeCast for int256;\n using SafeCast for uint256;\n\n struct CreateGlvShiftParams {\n address glv;\n address fromMarket;\n address toMarket;\n uint256 marketTokenAmount;\n uint256 minMarketTokens;\n }\n\n struct ExecuteGlvShiftParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n IOracle oracle;\n MultichainVault multichainVault;\n ShiftVault shiftVault;\n GlvVault glvVault;\n IDepositHandler depositHandler;\n IWithdrawalHandler withdrawalHandler;\n ISwapHandler swapHandler;\n bytes32 key;\n address keeper;\n }\n\n struct ExecuteGlvShiftCache {\n Market.Props fromMarket;\n Market.Props toMarket;\n Shift.Props shift;\n MarketPoolValueInfo.Props fromMarketPoolValueInfo;\n uint256 fromMarketTokenSupply;\n MarketPoolValueInfo.Props toMarketPoolValueInfo;\n uint256 toMarketTokenSupply;\n uint256 marketTokensUsd;\n uint256 receivedMarketTokens;\n uint256 receivedMarketTokensUsd;\n bytes32 shiftKey;\n uint256 glvValue;\n uint256 glvSupply;\n }\n\n function createGlvShift(\n DataStore dataStore,\n EventEmitter eventEmitter,\n CreateGlvShiftParams memory params\n ) external returns (bytes32) {\n GlvUtils.validateGlv(dataStore, params.glv);\n GlvUtils.validateGlvMarket(dataStore, params.glv, params.fromMarket, false);\n GlvUtils.validateGlvMarket(dataStore, params.glv, params.toMarket, true);\n\n validateGlvShiftInterval(dataStore, params.glv);\n\n uint256 fromMarketTokenBalance = GlvToken(payable(params.glv)).tokenBalances(params.fromMarket);\n if (fromMarketTokenBalance < params.marketTokenAmount) {\n revert Errors.GlvInsufficientMarketTokenBalance(\n params.glv,\n params.fromMarket,\n fromMarketTokenBalance,\n params.marketTokenAmount\n );\n }\n\n MarketUtils.validateEnabledMarket(dataStore, params.fromMarket);\n MarketUtils.validateEnabledMarket(dataStore, params.toMarket);\n\n GlvShift.Props memory glvShift = GlvShift.Props(\n GlvShift.Addresses({glv: params.glv, fromMarket: params.fromMarket, toMarket: params.toMarket}),\n GlvShift.Numbers({\n marketTokenAmount: params.marketTokenAmount,\n minMarketTokens: params.minMarketTokens,\n updatedAtTime: Chain.currentTimestamp()\n })\n );\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n\n GlvShiftStoreUtils.set(dataStore, key, glvShift);\n\n GlvShiftEventUtils.emitGlvShiftCreated(eventEmitter, key, glvShift);\n\n return key;\n }\n\n function validateGlvShiftInterval(DataStore dataStore, address glv) internal view {\n uint256 glvShiftMinInterval = dataStore.getUint(Keys.glvShiftMinIntervalKey(glv));\n if (glvShiftMinInterval == 0) {\n return;\n }\n\n uint256 glvShiftLastExecutedAt = dataStore.getUint(Keys.glvShiftLastExecutedAtKey(glv));\n if (Chain.currentTimestamp() < glvShiftLastExecutedAt + glvShiftMinInterval) {\n revert Errors.GlvShiftIntervalNotYetPassed(\n Chain.currentTimestamp(),\n glvShiftLastExecutedAt,\n glvShiftMinInterval\n );\n }\n }\n\n function executeGlvShift(\n ExecuteGlvShiftParams memory params,\n GlvShift.Props memory glvShift\n ) external returns (uint256) {\n GlvShiftStoreUtils.remove(params.dataStore, params.key);\n\n validateGlvShiftInterval(params.dataStore, glvShift.glv());\n params.dataStore.setUint(Keys.glvShiftLastExecutedAtKey(glvShift.glv()), Chain.currentTimestamp());\n\n Bank(payable(glvShift.glv())).transferOut(\n glvShift.fromMarket(),\n address(params.shiftVault),\n glvShift.marketTokenAmount()\n );\n params.shiftVault.syncTokenBalance(glvShift.fromMarket());\n\n ExecuteGlvShiftCache memory cache;\n cache.shift = Shift.Props(\n Shift.Addresses({\n account: glvShift.glv(),\n receiver: glvShift.glv(),\n callbackContract: address(0),\n uiFeeReceiver: address(0),\n fromMarket: glvShift.fromMarket(),\n toMarket: glvShift.toMarket()\n }),\n Shift.Numbers({\n minMarketTokens: glvShift.minMarketTokens(),\n marketTokenAmount: glvShift.marketTokenAmount(),\n updatedAtTime: glvShift.updatedAtTime(),\n executionFee: 0,\n callbackGasLimit: 0,\n srcChainId: 0 // srcChainId is the current block.chainId\n }),\n new bytes32[](0)\n );\n\n cache.shiftKey = NonceUtils.getNextKey(params.dataStore);\n params.dataStore.addBytes32(Keys.SHIFT_LIST, cache.shiftKey);\n ShiftEventUtils.emitShiftCreated(params.eventEmitter, cache.shiftKey, cache.shift);\n\n ShiftUtils.ExecuteShiftParams memory executeShiftParams = ShiftUtils.ExecuteShiftParams({\n dataStore: params.dataStore,\n eventEmitter: params.eventEmitter,\n multichainVault: params.multichainVault,\n shiftVault: params.shiftVault,\n oracle: params.oracle,\n depositHandler: params.depositHandler,\n withdrawalHandler: params.withdrawalHandler,\n swapHandler: params.swapHandler,\n key: cache.shiftKey,\n keeper: params.keeper,\n\n // executionFee is not used for GlvShift's\n // pass gasleft() not to break startGas calculations inside ShiftUtils\n startingGas: gasleft()\n });\n\n cache.receivedMarketTokens = ShiftUtils.executeShift(executeShiftParams, cache.shift);\n\n GlvToken(payable(glvShift.glv())).syncTokenBalance(glvShift.toMarket());\n\n cache.toMarket = MarketStoreUtils.get(params.dataStore, glvShift.toMarket());\n\n cache.toMarketPoolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n cache.toMarket,\n params.oracle.getPrimaryPrice(cache.toMarket.indexToken),\n params.oracle.getPrimaryPrice(cache.toMarket.longToken),\n params.oracle.getPrimaryPrice(cache.toMarket.shortToken),\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n true // maximize\n );\n cache.toMarketTokenSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(glvShift.toMarket())));\n\n GlvUtils.validateGlvMarketTokenBalance(\n params.dataStore,\n glvShift.glv(),\n cache.toMarket,\n cache.toMarketPoolValueInfo.poolValue.toUint256(),\n cache.toMarketTokenSupply\n );\n cache.receivedMarketTokensUsd = MarketUtils.marketTokenAmountToUsd(\n cache.receivedMarketTokens,\n cache.toMarketPoolValueInfo.poolValue.toUint256(),\n cache.toMarketTokenSupply\n );\n\n cache.fromMarket = MarketStoreUtils.get(params.dataStore, glvShift.fromMarket());\n cache.fromMarketPoolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n cache.fromMarket,\n params.oracle.getPrimaryPrice(cache.fromMarket.indexToken),\n params.oracle.getPrimaryPrice(cache.fromMarket.longToken),\n params.oracle.getPrimaryPrice(cache.fromMarket.shortToken),\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n true // maximize\n );\n cache.fromMarketTokenSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(glvShift.fromMarket())));\n\n cache.marketTokensUsd = MarketUtils.marketTokenAmountToUsd(\n glvShift.marketTokenAmount(),\n cache.fromMarketPoolValueInfo.poolValue.toUint256(),\n cache.fromMarketTokenSupply\n );\n\n validatePriceImpact(params.dataStore, glvShift.glv(), cache.marketTokensUsd, cache.receivedMarketTokensUsd);\n\n GlvShiftEventUtils.emitGlvShiftExecuted(params.eventEmitter, params.key, cache.receivedMarketTokens);\n\n cache.glvValue = GlvUtils.getGlvValue(\n params.dataStore,\n params.oracle,\n glvShift.glv(),\n true // maximize\n );\n cache.glvSupply = GlvToken(payable(glvShift.glv())).totalSupply();\n GlvEventUtils.emitGlvValueUpdated(params.eventEmitter, glvShift.glv(), cache.glvValue, cache.glvSupply);\n\n return cache.receivedMarketTokens;\n }\n\n function cancelGlvShift(\n DataStore dataStore,\n EventEmitter eventEmitter,\n bytes32 key,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n GlvShiftStoreUtils.remove(dataStore, key);\n\n GlvShiftEventUtils.emitGlvShiftCancelled(eventEmitter, key, reason, reasonBytes);\n }\n\n function validatePriceImpact(\n DataStore dataStore,\n address glv,\n uint256 marketTokensUsd,\n uint256 receivedMarketTokensUsd\n ) internal view {\n if (marketTokensUsd < receivedMarketTokensUsd) {\n // price impact is positive, no need to validate it\n return;\n }\n\n uint256 glvMaxShiftPriceImpactFactor = dataStore.getUint(Keys.glvShiftMaxPriceImpactFactorKey(glv));\n\n uint256 effectivePriceImpactFactor = Precision.toFactor(\n marketTokensUsd - receivedMarketTokensUsd,\n marketTokensUsd\n );\n if (effectivePriceImpactFactor > glvMaxShiftPriceImpactFactor) {\n revert Errors.GlvShiftMaxPriceImpactExceeded(effectivePriceImpactFactor, glvMaxShiftPriceImpactFactor);\n }\n }\n}\n" + }, + "contracts/glv/GlvStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Glv.sol\";\n\nlibrary GlvStoreUtils {\n using Glv for Glv.Props;\n\n bytes32 public constant GLV_SALT = keccak256(abi.encode(\"GLV_SALT\"));\n bytes32 public constant GLV_TOKEN = keccak256(abi.encode(\"GLV_TOKEN\"));\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\"LONG_TOKEN\"));\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\"SHORT_TOKEN\"));\n\n function get(DataStore dataStore, address key) public view returns (Glv.Props memory) {\n Glv.Props memory glv;\n if (!dataStore.containsAddress(Keys.GLV_LIST, key)) {\n return glv;\n }\n\n glv.glvToken = dataStore.getAddress(\n keccak256(abi.encode(key, GLV_TOKEN))\n );\n\n glv.longToken = dataStore.getAddress(\n keccak256(abi.encode(key, LONG_TOKEN))\n );\n\n glv.shortToken = dataStore.getAddress(\n keccak256(abi.encode(key, SHORT_TOKEN))\n );\n\n return glv;\n }\n\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Glv.Props memory) {\n address key = dataStore.getAddress(getGlvSaltHash(salt));\n return get(dataStore, key);\n }\n\n function set(DataStore dataStore, address key, bytes32 salt, Glv.Props memory glv) external {\n dataStore.addAddress(\n Keys.GLV_LIST,\n key\n );\n\n // the salt is based on the glv props while the key gives the glv's address\n // use the salt to store a reference to the key to allow the key to be retrieved\n // using just the salt value\n dataStore.setAddress(\n getGlvSaltHash(salt),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, GLV_TOKEN)),\n glv.glvToken\n );\n\n\n dataStore.setAddress(\n keccak256(abi.encode(key, LONG_TOKEN)),\n glv.longToken\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, SHORT_TOKEN)),\n glv.shortToken\n );\n }\n\n function remove(DataStore dataStore, address key) external {\n if (!dataStore.containsAddress(Keys.GLV_LIST, key)) {\n revert Errors.GlvNotFound(key);\n }\n\n dataStore.removeAddress(\n Keys.GLV_LIST,\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, GLV_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, LONG_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, SHORT_TOKEN))\n );\n }\n\n function getGlvSaltHash(bytes32 salt) internal pure returns (bytes32) {\n return keccak256(abi.encode(GLV_SALT, salt));\n }\n\n function getGlvCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getAddressCount(Keys.GLV_LIST);\n }\n\n function getGlvKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\n return dataStore.getAddressValuesAt(Keys.GLV_LIST, start, end);\n }\n}\n" + }, + "contracts/glv/GlvToken.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../bank/StrictBank.sol\";\n\ncontract GlvToken is ERC20, StrictBank {\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) StrictBank(_roleStore, _dataStore) {}\n\n function mint(address account, uint256 amount) external onlyController {\n _mint(account, amount);\n }\n\n function burn(address account, uint256 amount) external onlyController {\n _burn(account, amount);\n }\n}\n" + }, + "contracts/glv/GlvUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../market/Market.sol\";\nimport \"../market/MarketUtils.sol\";\nimport \"./GlvToken.sol\";\nimport \"./GlvEventUtils.sol\";\nimport \"./GlvStoreUtils.sol\";\n\nlibrary GlvUtils {\n using SafeCast for int256;\n using SafeCast for uint256;\n\n struct GetGlvValueCache {\n bytes32 marketListKey;\n uint256 marketCount;\n uint256 glvValue;\n Price.Props indexTokenPrice;\n Price.Props longTokenPrice;\n Price.Props shortTokenPrice;\n Market.Props market;\n }\n\n // @dev get the USD value of the Glv\n // @param dataStore DataStore\n // @param oracle IOracle\n // @param glv Glv\n // @param maximize\n // @return the USD value of the Glv\n function getGlvValue(\n DataStore dataStore,\n IOracle oracle,\n address glv,\n bool maximize\n ) public view returns (uint256) {\n GetGlvValueCache memory cache;\n cache.marketListKey = Keys.glvSupportedMarketListKey(glv);\n cache.marketCount = dataStore.getAddressCount(cache.marketListKey);\n\n address[] memory marketAddresses = dataStore.getAddressValuesAt(cache.marketListKey, 0, cache.marketCount);\n for (uint256 i = 0; i < marketAddresses.length; i++) {\n address marketAddress = marketAddresses[i];\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n if (i == 0) {\n cache.longTokenPrice = oracle.getPrimaryPrice(market.longToken);\n cache.shortTokenPrice = oracle.getPrimaryPrice(market.shortToken);\n }\n cache.glvValue += _getGlvMarketValue(\n dataStore,\n glv,\n marketAddress,\n oracle.getPrimaryPrice(market.indexToken),\n cache.longTokenPrice,\n cache.shortTokenPrice,\n maximize\n );\n }\n\n return cache.glvValue;\n }\n\n function getGlvValue(\n DataStore dataStore,\n address[] memory marketAddresses,\n Price.Props[] memory indexTokenPrices,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n address glv,\n bool maximize\n ) public view returns (uint256) {\n GetGlvValueCache memory cache;\n\n for (uint256 i = 0; i < marketAddresses.length; i++) {\n address marketAddress = marketAddresses[i];\n cache.indexTokenPrice = indexTokenPrices[i];\n\n cache.glvValue += _getGlvMarketValue(\n dataStore,\n glv,\n marketAddress,\n cache.indexTokenPrice,\n longTokenPrice,\n shortTokenPrice,\n maximize\n );\n }\n\n return cache.glvValue;\n }\n\n function _getGlvMarketValue(\n DataStore dataStore,\n address glv,\n address marketAddress,\n Price.Props memory indexTokenPrice,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n bool maximize\n ) internal view returns (uint256) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n\n uint256 marketTokenSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(marketAddress)));\n uint256 balance = GlvToken(payable(glv)).tokenBalances(marketAddress);\n\n if (balance == 0) {\n return 0;\n }\n\n MarketPoolValueInfo.Props memory marketPoolValueInfo = MarketUtils.getPoolValueInfo(\n dataStore,\n market,\n indexTokenPrice,\n longTokenPrice,\n shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n maximize\n );\n\n if (marketPoolValueInfo.poolValue < 0) {\n revert Errors.GlvNegativeMarketPoolValue(glv, marketAddress);\n }\n\n return\n MarketUtils.marketTokenAmountToUsd(balance, marketPoolValueInfo.poolValue.toUint256(), marketTokenSupply);\n }\n\n function getGlvTokenPrice(\n DataStore dataStore,\n IOracle oracle,\n address glv,\n bool maximize\n ) internal view returns (uint256, uint256, uint256) {\n uint256 value = getGlvValue(dataStore, oracle, glv, maximize);\n uint256 supply = ERC20(glv).totalSupply();\n\n return _getGlvTokenPrice(value, supply);\n }\n\n function getGlvTokenPrice(\n DataStore dataStore,\n address[] memory marketAddresses,\n Price.Props[] memory indexTokenPrices,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n address glv,\n bool maximize\n ) internal view returns (uint256, uint256, uint256) {\n uint256 value = getGlvValue(\n dataStore,\n marketAddresses,\n indexTokenPrices,\n longTokenPrice,\n shortTokenPrice,\n glv,\n maximize\n );\n uint256 supply = ERC20(glv).totalSupply();\n\n return _getGlvTokenPrice(value, supply);\n }\n\n function _getGlvTokenPrice(uint256 value, uint256 supply) internal pure returns (uint256, uint256, uint256) {\n // if the supply is zero then treat the market token price as 1 USD\n if (supply == 0) {\n return (Precision.FLOAT_PRECISION, value, supply);\n }\n if (value == 0) {\n return (0, value, supply);\n }\n return (Precision.mulDiv(Precision.WEI_PRECISION, value, supply), value, supply);\n }\n\n function usdToGlvTokenAmount(\n uint256 usdValue,\n uint256 glvValue,\n uint256 glvSupply\n ) internal pure returns (uint256) {\n // if the supply and glvValue is zero, use 1 USD as the token price\n if (glvSupply == 0 && glvValue == 0) {\n return Precision.floatToWei(usdValue);\n }\n\n // if the supply is zero and the glvValue is more than zero,\n // then include the glvValue for the amount of tokens minted so that\n // the market token price after mint would be 1 USD\n if (glvSupply == 0 && glvValue > 0) {\n return Precision.floatToWei(glvValue + usdValue);\n }\n\n // round market tokens down\n return Precision.mulDiv(glvSupply, usdValue, glvValue);\n }\n\n function glvTokenAmountToUsd(\n uint256 glvTokenAmount,\n uint256 glvValue,\n uint256 glvSupply\n ) internal pure returns (uint256) {\n if (glvSupply == 0) {\n revert Errors.EmptyGlvTokenSupply();\n }\n\n return Precision.mulDiv(glvValue, glvTokenAmount, glvSupply);\n }\n\n function validateGlvMarket(DataStore dataStore, address glv, address market, bool shouldBeEnabled) public view {\n if (!dataStore.containsAddress(Keys.glvSupportedMarketListKey(glv), market)) {\n revert Errors.GlvUnsupportedMarket(glv, market);\n }\n\n if (shouldBeEnabled && dataStore.getBool(Keys.isGlvMarketDisabledKey(glv, market))) {\n revert Errors.GlvDisabledMarket(glv, market);\n }\n }\n\n function validateGlv(DataStore dataStore, address glv) public view {\n if (!dataStore.containsAddress(Keys.GLV_LIST, glv)) {\n revert Errors.EmptyGlv(glv);\n }\n }\n\n function getGlvMarketCount(DataStore dataStore, address glv) external view returns (uint256) {\n return dataStore.getAddressCount(Keys.glvSupportedMarketListKey(glv));\n }\n\n function validateGlvMarketTokenBalance(\n DataStore dataStore,\n address glv,\n Market.Props memory market,\n uint256 marketPoolValue,\n uint256 marketTokenSupply\n ) external view {\n uint256 maxMarketTokenBalanceUsd = dataStore.getUint(\n Keys.glvMaxMarketTokenBalanceUsdKey(glv, market.marketToken)\n );\n uint256 maxMarketTokenBalanceAmount = dataStore.getUint(\n Keys.glvMaxMarketTokenBalanceAmountKey(glv, market.marketToken)\n );\n\n if (maxMarketTokenBalanceAmount == 0 && maxMarketTokenBalanceUsd == 0) {\n return;\n }\n\n uint256 marketTokenBalanceAmount = GlvToken(payable(glv)).tokenBalances(market.marketToken);\n if (maxMarketTokenBalanceAmount > 0 && marketTokenBalanceAmount > maxMarketTokenBalanceAmount) {\n revert Errors.GlvMaxMarketTokenBalanceAmountExceeded(\n glv,\n market.marketToken,\n maxMarketTokenBalanceAmount,\n marketTokenBalanceAmount\n );\n }\n\n if (maxMarketTokenBalanceUsd > 0) {\n uint256 marketTokenBalanceUsd = MarketUtils.marketTokenAmountToUsd(\n marketTokenBalanceAmount,\n marketPoolValue,\n marketTokenSupply\n );\n if (marketTokenBalanceUsd > maxMarketTokenBalanceUsd) {\n revert Errors.GlvMaxMarketTokenBalanceUsdExceeded(\n glv,\n market.marketToken,\n maxMarketTokenBalanceUsd,\n marketTokenBalanceUsd\n );\n }\n }\n }\n\n function addMarketToGlv(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address glvAddress,\n address marketAddress\n ) external {\n validateGlv(dataStore, glvAddress);\n\n Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, marketAddress);\n Glv.Props memory glv = GlvStoreUtils.get(dataStore, glvAddress);\n if (market.longToken != glv.longToken) {\n revert Errors.GlvInvalidLongToken(glvAddress, market.longToken, glv.longToken);\n }\n if (market.shortToken != glv.shortToken) {\n revert Errors.GlvInvalidShortToken(glvAddress, market.shortToken, glv.shortToken);\n }\n\n bytes32 key = Keys.glvSupportedMarketListKey(glvAddress);\n if (dataStore.containsAddress(key, marketAddress)) {\n revert Errors.GlvMarketAlreadyExists(glvAddress, marketAddress);\n }\n dataStore.addAddress(key, marketAddress);\n\n validateGlvMarketCount(dataStore, glvAddress);\n\n GlvEventUtils.emitGlvMarketAdded(eventEmitter, glvAddress, market.marketToken);\n }\n\n function validateGlvMarketCount(DataStore dataStore, address glvAddress) internal view {\n uint256 glvMaxMarketCount = dataStore.getUint(Keys.GLV_MAX_MARKET_COUNT);\n if (glvMaxMarketCount > 0) {\n bytes32 key = Keys.glvSupportedMarketListKey(glvAddress);\n uint256 glvMarketCount = dataStore.getAddressCount(key);\n if (glvMarketCount > glvMaxMarketCount) {\n revert Errors.GlvMaxMarketCountExceeded(glvAddress, glvMaxMarketCount);\n }\n }\n }\n\n function removeMarketFromGlv(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address glvAddress,\n address marketAddress\n ) external {\n validateGlv(dataStore, glvAddress);\n validateGlvMarket(dataStore, glvAddress, marketAddress, false);\n\n if (!dataStore.getBool(Keys.isGlvMarketDisabledKey(glvAddress, marketAddress))) {\n revert Errors.GlvEnabledMarket(glvAddress, marketAddress);\n }\n\n uint256 balance = GlvToken(payable(glvAddress)).tokenBalances(marketAddress);\n if (balance != 0) {\n revert Errors.GlvNonZeroMarketBalance(glvAddress, marketAddress);\n }\n\n bytes32 key = Keys.glvSupportedMarketListKey(glvAddress);\n dataStore.removeAddress(key, marketAddress);\n\n GlvEventUtils.emitGlvMarketRemoved(eventEmitter, glvAddress, marketAddress);\n }\n}\n" + }, + "contracts/glv/GlvVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/StrictBank.sol\";\n\ncontract GlvVault is StrictBank {\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\n}\n" + }, + "contracts/glv/glvWithdrawal/GlvWithdrawal.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n/**\n * @title Withdrawal\n * @dev Struct for withdrawals\n */\nlibrary GlvWithdrawal {\n // @dev there is a limit on the number of fields a struct can have when being passed\n // or returned as a memory variable which can cause \"Stack too deep\" errors\n // use sub-structs to avoid this issue\n // @param addresses address values\n // @param numbers number values\n // @param flags boolean values\n // @param _dataList a list of bytes32 values that can be used for additional data\n struct Props {\n Addresses addresses;\n Numbers numbers;\n Flags flags;\n bytes32[] _dataList;\n }\n\n // @param account The account to withdraw for.\n // @param receiver The address that will receive the withdrawn tokens.\n // @param callbackContract The contract that will be called back.\n // @param uiFeeReceiver The ui fee receiver.\n // @param market The market on which the withdrawal will be executed.\n // @param glv\n struct Addresses {\n address glv;\n address market;\n address account;\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n\n // @param glvTokenAmount The amount of market tokens that will be withdrawn.\n // @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn.\n // @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn.\n // @param executionFee The execution fee for the withdrawal.\n // @param callbackGasLimit The gas limit for calling the callback contract.\n // @param srcChainId The source chain id.\n struct Numbers {\n uint256 glvTokenAmount;\n uint256 minLongTokenAmount;\n uint256 minShortTokenAmount;\n uint256 updatedAtTime;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 srcChainId;\n }\n\n // @param shouldUnwrapNativeToken whether to unwrap the native token when\n struct Flags {\n bool shouldUnwrapNativeToken;\n }\n\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n function receiver(Props memory props) internal pure returns (address) {\n return props.addresses.receiver;\n }\n\n function setReceiver(Props memory props, address value) internal pure {\n props.addresses.receiver = value;\n }\n\n function callbackContract(Props memory props) internal pure returns (address) {\n return props.addresses.callbackContract;\n }\n\n function setCallbackContract(Props memory props, address value) internal pure {\n props.addresses.callbackContract = value;\n }\n\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.uiFeeReceiver;\n }\n\n function setUiFeeReceiver(Props memory props, address value) internal pure {\n props.addresses.uiFeeReceiver = value;\n }\n\n function market(Props memory props) internal pure returns (address) {\n return props.addresses.market;\n }\n\n function setMarket(Props memory props, address value) internal pure {\n props.addresses.market = value;\n }\n\n function glv(Props memory props) internal pure returns (address) {\n return props.addresses.glv;\n }\n\n function setGlv(Props memory props, address value) internal pure {\n props.addresses.glv = value;\n }\n\n function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.longTokenSwapPath;\n }\n\n function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.longTokenSwapPath = value;\n }\n\n function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.shortTokenSwapPath;\n }\n\n function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.shortTokenSwapPath = value;\n }\n\n function glvTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.glvTokenAmount;\n }\n\n function setGlvTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.glvTokenAmount = value;\n }\n\n function minLongTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.minLongTokenAmount;\n }\n\n function setMinLongTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.minLongTokenAmount = value;\n }\n\n function minShortTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.minShortTokenAmount;\n }\n\n function setMinShortTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.minShortTokenAmount = value;\n }\n\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n\n function executionFee(Props memory props) internal pure returns (uint256) {\n return props.numbers.executionFee;\n }\n\n function setExecutionFee(Props memory props, uint256 value) internal pure {\n props.numbers.executionFee = value;\n }\n\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\n return props.numbers.callbackGasLimit;\n }\n\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\n props.numbers.callbackGasLimit = value;\n }\n\n function srcChainId(Props memory props) internal pure returns (uint256) {\n return props.numbers.srcChainId;\n }\n\n function setSrcChainId(Props memory props, uint256 value) internal pure {\n props.numbers.srcChainId = value;\n }\n\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\n return props.flags.shouldUnwrapNativeToken;\n }\n\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\n props.flags.shouldUnwrapNativeToken = value;\n }\n\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\n return props._dataList;\n }\n\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\n props._dataList = value;\n }\n}\n" + }, + "contracts/glv/glvWithdrawal/GlvWithdrawalEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../event/EventEmitter.sol\";\nimport \"../../event/EventUtils.sol\";\nimport \"../../utils/Cast.sol\";\n\nimport \"./GlvWithdrawal.sol\";\n\nlibrary GlvWithdrawalEventUtils {\n using GlvWithdrawal for GlvWithdrawal.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitGlvWithdrawalCreated(\n EventEmitter eventEmitter,\n bytes32 key,\n GlvWithdrawal.Props memory glvWithdrawal\n ) external {\n EventUtils.EventLogData memory eventData = createEventData(glvWithdrawal);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog2(\"GlvWithdrawalCreated\", key, Cast.toBytes32(glvWithdrawal.account()), eventData);\n }\n\n function emitGlvWithdrawalExecuted(EventEmitter eventEmitter, bytes32 key, address account) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventEmitter.emitEventLog2(\"GlvWithdrawalExecuted\", key, Cast.toBytes32(account), eventData);\n }\n\n function emitGlvWithdrawalCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\"GlvWithdrawalCancelled\", key, Cast.toBytes32(account), eventData);\n }\n\n function createEventData(GlvWithdrawal.Props memory glvWithdrawal) public pure returns (EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(6);\n eventData.addressItems.setItem(0, \"account\", glvWithdrawal.account());\n eventData.addressItems.setItem(1, \"receiver\", glvWithdrawal.receiver());\n eventData.addressItems.setItem(2, \"callbackContract\", glvWithdrawal.callbackContract());\n eventData.addressItems.setItem(3, \"market\", glvWithdrawal.market());\n eventData.addressItems.setItem(4, \"glv\", glvWithdrawal.glv());\n eventData.addressItems.setItem(5, \"uiFeeReceiver\", glvWithdrawal.uiFeeReceiver());\n\n eventData.addressItems.initArrayItems(2);\n eventData.addressItems.setItem(0, \"longTokenSwapPath\", glvWithdrawal.longTokenSwapPath());\n eventData.addressItems.setItem(1, \"shortTokenSwapPath\", glvWithdrawal.shortTokenSwapPath());\n\n eventData.uintItems.initItems(7);\n eventData.uintItems.setItem(0, \"glvTokenAmount\", glvWithdrawal.glvTokenAmount());\n eventData.uintItems.setItem(1, \"minLongTokenAmount\", glvWithdrawal.minLongTokenAmount());\n eventData.uintItems.setItem(2, \"minShortTokenAmount\", glvWithdrawal.minShortTokenAmount());\n eventData.uintItems.setItem(3, \"updatedAtTime\", glvWithdrawal.updatedAtTime());\n eventData.uintItems.setItem(4, \"executionFee\", glvWithdrawal.executionFee());\n eventData.uintItems.setItem(5, \"callbackGasLimit\", glvWithdrawal.callbackGasLimit());\n eventData.uintItems.setItem(6, \"srcChainId\", glvWithdrawal.srcChainId());\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"shouldUnwrapNativeToken\", glvWithdrawal.shouldUnwrapNativeToken());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", glvWithdrawal.dataList());\n return eventData;\n }\n}\n" + }, + "contracts/glv/glvWithdrawal/GlvWithdrawalStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../data/Keys.sol\";\nimport \"../../data/DataStore.sol\";\n\nimport \"./GlvWithdrawal.sol\";\n\n/**\n * @title GlvWithdrawalStoreUtils\n * @dev Library for withdrawal storage functions\n */\nlibrary GlvWithdrawalStoreUtils {\n using GlvWithdrawal for GlvWithdrawal.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant RECEIVER = keccak256(abi.encode(\"RECEIVER\"));\n bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode(\"CALLBACK_CONTRACT\"));\n bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode(\"UI_FEE_RECEIVER\"));\n bytes32 public constant MARKET = keccak256(abi.encode(\"MARKET\"));\n bytes32 public constant GLV = keccak256(abi.encode(\"GLV\"));\n bytes32 public constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode(\"LONG_TOKEN_SWAP_PATH\"));\n bytes32 public constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode(\"SHORT_TOKEN_SWAP_PATH\"));\n\n bytes32 public constant GLV_TOKEN_AMOUNT = keccak256(abi.encode(\"GLV_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_LONG_TOKEN_AMOUNT = keccak256(abi.encode(\"MIN_LONG_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_SHORT_TOKEN_AMOUNT = keccak256(abi.encode(\"MIN_SHORT_TOKEN_AMOUNT\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n bytes32 public constant EXECUTION_FEE = keccak256(abi.encode(\"EXECUTION_FEE\"));\n bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"CALLBACK_GAS_LIMIT\"));\n bytes32 public constant SRC_CHAIN_ID = keccak256(abi.encode(\"SRC_CHAIN_ID\"));\n\n bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode(\"SHOULD_UNWRAP_NATIVE_TOKEN\"));\n\n bytes32 public constant DATA_LIST = keccak256(abi.encode(\"DATA_LIST\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (GlvWithdrawal.Props memory) {\n GlvWithdrawal.Props memory withdrawal;\n if (!dataStore.containsBytes32(Keys.GLV_WITHDRAWAL_LIST, key)) {\n return withdrawal;\n }\n\n withdrawal.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n withdrawal.setReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, RECEIVER))\n ));\n\n withdrawal.setCallbackContract(dataStore.getAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n ));\n\n withdrawal.setUiFeeReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n ));\n\n withdrawal.setMarket(dataStore.getAddress(\n keccak256(abi.encode(key, MARKET))\n ));\n\n withdrawal.setGlv(dataStore.getAddress(\n keccak256(abi.encode(key, GLV))\n ));\n\n withdrawal.setLongTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n ));\n\n withdrawal.setShortTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n ));\n\n withdrawal.setGlvTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, GLV_TOKEN_AMOUNT))\n ));\n\n withdrawal.setMinLongTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))\n ));\n\n withdrawal.setMinShortTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))\n ));\n\n withdrawal.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n withdrawal.setExecutionFee(dataStore.getUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n ));\n\n withdrawal.setCallbackGasLimit(dataStore.getUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n ));\n\n withdrawal.setSrcChainId(dataStore.getUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n ));\n\n withdrawal.setShouldUnwrapNativeToken(dataStore.getBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n ));\n\n withdrawal.setDataList(dataStore.getBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n ));\n\n return withdrawal;\n }\n\n function set(DataStore dataStore, bytes32 key, GlvWithdrawal.Props memory withdrawal) external {\n dataStore.addBytes32(\n Keys.GLV_WITHDRAWAL_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountGlvWithdrawalListKey(withdrawal.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n withdrawal.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, RECEIVER)),\n withdrawal.receiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT)),\n withdrawal.callbackContract()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER)),\n withdrawal.uiFeeReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET)),\n withdrawal.market()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, GLV)),\n withdrawal.glv()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),\n withdrawal.longTokenSwapPath()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),\n withdrawal.shortTokenSwapPath()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, GLV_TOKEN_AMOUNT)),\n withdrawal.glvTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)),\n withdrawal.minLongTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)),\n withdrawal.minShortTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n withdrawal.updatedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, EXECUTION_FEE)),\n withdrawal.executionFee()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),\n withdrawal.callbackGasLimit()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID)),\n withdrawal.srcChainId()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),\n withdrawal.shouldUnwrapNativeToken()\n );\n\n dataStore.setBytes32Array(\n keccak256(abi.encode(key, DATA_LIST)),\n withdrawal.dataList()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.GLV_WITHDRAWAL_LIST, key)) {\n revert Errors.GlvWithdrawalNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.GLV_WITHDRAWAL_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountGlvWithdrawalListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, GLV))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, GLV_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n );\n\n dataStore.removeBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n );\n }\n\n function getGlvWithdrawalCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.GLV_WITHDRAWAL_LIST);\n }\n\n function getGlvWithdrawalKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.GLV_WITHDRAWAL_LIST, start, end);\n }\n\n function getAccountGlvWithdrawalCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountGlvWithdrawalListKey(account));\n }\n\n function getAccountGlvWithdrawalKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountGlvWithdrawalListKey(account), start, end);\n }\n}\n" + }, + "contracts/glv/glvWithdrawal/GlvWithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../withdrawal/ExecuteWithdrawalUtils.sol\";\n\nimport \"../../nonce/NonceUtils.sol\";\n\nimport \"../GlvVault.sol\";\nimport \"../GlvUtils.sol\";\nimport \"./GlvWithdrawalStoreUtils.sol\";\nimport \"./GlvWithdrawalEventUtils.sol\";\nimport \"./IGlvWithdrawalUtils.sol\";\n\nlibrary GlvWithdrawalUtils {\n using GlvWithdrawal for GlvWithdrawal.Props;\n using SafeCast for int256;\n using SafeCast for uint256;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.AddressItems;\n\n struct ExecuteGlvWithdrawalParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n IMultichainTransferRouter multichainTransferRouter;\n GlvVault glvVault;\n IOracle oracle;\n ISwapHandler swapHandler;\n bytes32 key;\n uint256 startingGas;\n address keeper;\n }\n\n struct ExecuteGlvWithdrawalCache {\n uint256 glvValue;\n uint256 marketCount;\n uint256 oraclePriceCount;\n uint256 marketTokenAmount;\n }\n\n struct CancelGlvWithdrawalParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n GlvVault glvVault;\n bytes32 key;\n address keeper;\n uint256 startingGas;\n string reason;\n bytes reasonBytes;\n }\n\n function createGlvWithdrawal(\n DataStore dataStore,\n EventEmitter eventEmitter,\n GlvVault glvVault,\n address account,\n uint256 srcChainId,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams memory params\n ) external returns (bytes32) {\n AccountUtils.validateAccount(account);\n GlvUtils.validateGlv(dataStore, params.addresses.glv);\n GlvUtils.validateGlvMarket(dataStore, params.addresses.glv, params.addresses.market, false);\n\n MarketUtils.validateEnabledMarket(dataStore, params.addresses.market);\n MarketUtils.validateSwapPath(dataStore, params.addresses.longTokenSwapPath);\n MarketUtils.validateSwapPath(dataStore, params.addresses.shortTokenSwapPath);\n\n address wnt = TokenUtils.wnt(dataStore);\n uint256 wntAmount = glvVault.recordTransferIn(wnt);\n if (wntAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);\n }\n params.executionFee = wntAmount;\n\n AccountUtils.validateReceiver(params.addresses.receiver);\n\n uint256 glvTokenAmount = glvVault.recordTransferIn(params.addresses.glv);\n\n if (glvTokenAmount == 0) {\n revert Errors.EmptyGlvWithdrawalAmount();\n }\n\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawal.Props(\n GlvWithdrawal.Addresses({\n account: account,\n glv: params.addresses.glv,\n receiver: params.addresses.receiver,\n callbackContract: params.addresses.callbackContract,\n uiFeeReceiver: params.addresses.uiFeeReceiver,\n market: params.addresses.market,\n longTokenSwapPath: params.addresses.longTokenSwapPath,\n shortTokenSwapPath: params.addresses.shortTokenSwapPath\n }),\n GlvWithdrawal.Numbers({\n glvTokenAmount: glvTokenAmount,\n minLongTokenAmount: params.minLongTokenAmount,\n minShortTokenAmount: params.minShortTokenAmount,\n updatedAtTime: Chain.currentTimestamp(),\n executionFee: params.executionFee,\n callbackGasLimit: params.callbackGasLimit,\n srcChainId: srcChainId\n }),\n GlvWithdrawal.Flags({shouldUnwrapNativeToken: params.shouldUnwrapNativeToken}),\n params.dataList\n );\n\n CallbackUtils.validateCallbackGasLimit(dataStore, params.callbackGasLimit);\n\n uint256 marketCount = GlvUtils.getGlvMarketCount(dataStore, glvWithdrawal.glv());\n GasUtils.validateExecutionFee(\n dataStore,\n GasUtils.estimateExecuteGlvWithdrawalGasLimit(dataStore, glvWithdrawal, marketCount), // estimatedGasLimit\n params.executionFee,\n GasUtils.estimateGlvWithdrawalOraclePriceCount(marketCount, params.addresses.longTokenSwapPath.length + params.addresses.shortTokenSwapPath.length) // oraclePriceCount\n );\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n\n GlvWithdrawalStoreUtils.set(dataStore, key, glvWithdrawal);\n\n GlvWithdrawalEventUtils.emitGlvWithdrawalCreated(eventEmitter, key, glvWithdrawal);\n\n return key;\n }\n\n function executeGlvWithdrawal(\n ExecuteGlvWithdrawalParams memory params,\n GlvWithdrawal.Props memory glvWithdrawal\n ) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n GlvWithdrawalStoreUtils.remove(params.dataStore, params.key, glvWithdrawal.account());\n\n ExecuteGlvWithdrawalCache memory cache;\n cache.marketTokenAmount = _getMarketTokenAmount(params.dataStore, params.oracle, glvWithdrawal);\n\n // burn GLV tokens before executing withdrawal\n // for both GLV amount and token amounts will be correct inside the receive() function\n // if receiver is a contract\n GlvToken(payable(glvWithdrawal.glv())).burn(address(params.glvVault), glvWithdrawal.glvTokenAmount());\n params.glvVault.syncTokenBalance(glvWithdrawal.glv());\n\n IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory withdrawalResult = _processMarketWithdrawal(\n params,\n glvWithdrawal,\n cache.marketTokenAmount\n );\n\n GlvWithdrawalEventUtils.emitGlvWithdrawalExecuted(params.eventEmitter, params.key, glvWithdrawal.account());\n\n cache.glvValue = GlvUtils.getGlvValue(\n params.dataStore,\n params.oracle,\n glvWithdrawal.glv(),\n true\n );\n GlvEventUtils.emitGlvValueUpdated(\n params.eventEmitter,\n glvWithdrawal.glv(),\n cache.glvValue,\n GlvToken(payable(glvWithdrawal.glv())).totalSupply()\n );\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"outputToken\", withdrawalResult.outputToken);\n eventData.addressItems.setItem(1, \"secondaryOutputToken\", withdrawalResult.secondaryOutputToken);\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"outputAmount\", withdrawalResult.outputAmount);\n eventData.uintItems.setItem(1, \"secondaryOutputAmount\", withdrawalResult.secondaryOutputAmount);\n CallbackUtils.afterGlvWithdrawalExecution(params.key, glvWithdrawal, eventData);\n\n\n BridgeOutFromControllerUtils.bridgeOutFromController(\n params.eventEmitter,\n params.multichainTransferRouter,\n BridgeOutFromControllerUtils.BridgeOutFromControllerParams({\n account: glvWithdrawal.account(), // account\n receiver: glvWithdrawal.receiver(), // receiver\n srcChainId: glvWithdrawal.srcChainId(),\n token: withdrawalResult.outputToken, // token\n amount: withdrawalResult.outputAmount, // amount\n secondaryToken: withdrawalResult.secondaryOutputToken, // secondaryToken\n secondaryAmount: withdrawalResult.secondaryOutputAmount, // secondaryAmount\n dataList: glvWithdrawal.dataList()\n })\n );\n\n cache.marketCount = GlvUtils.getGlvMarketCount(params.dataStore, glvWithdrawal.glv());\n cache.oraclePriceCount = GasUtils.estimateGlvWithdrawalOraclePriceCount(\n cache.marketCount,\n glvWithdrawal.longTokenSwapPath().length + glvWithdrawal.shortTokenSwapPath().length\n );\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.glvVault\n ),\n params.key,\n glvWithdrawal.callbackContract(),\n glvWithdrawal.executionFee(),\n params.startingGas,\n cache.oraclePriceCount,\n params.keeper,\n glvWithdrawal.receiver(),\n glvWithdrawal.srcChainId()\n );\n }\n\n function _processMarketWithdrawal(\n ExecuteGlvWithdrawalParams memory params,\n GlvWithdrawal.Props memory glvWithdrawal,\n uint256 marketTokenAmount\n ) private returns (IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory) {\n\n // srcChainId should be glvWithdrawal.srcChainId so that the withdrawn funds\n // are sent to the appropriate balance either the user's wallet balance\n // or the user's multichain balance\n Withdrawal.Props memory withdrawal = Withdrawal.Props(\n Withdrawal.Addresses({\n account: glvWithdrawal.glv(),\n receiver: glvWithdrawal.receiver(),\n callbackContract: address(0),\n uiFeeReceiver: glvWithdrawal.uiFeeReceiver(),\n market: glvWithdrawal.market(),\n longTokenSwapPath: glvWithdrawal.longTokenSwapPath(),\n shortTokenSwapPath: glvWithdrawal.shortTokenSwapPath()\n }),\n Withdrawal.Numbers({\n minLongTokenAmount: glvWithdrawal.minLongTokenAmount(),\n minShortTokenAmount: glvWithdrawal.minShortTokenAmount(),\n marketTokenAmount: marketTokenAmount,\n updatedAtTime: glvWithdrawal.updatedAtTime(),\n executionFee: 0,\n callbackGasLimit: 0,\n srcChainId: glvWithdrawal.srcChainId()\n }),\n Withdrawal.Flags({shouldUnwrapNativeToken: glvWithdrawal.shouldUnwrapNativeToken()}),\n new bytes32[](0)\n );\n\n bytes32 withdrawalKey = NonceUtils.getNextKey(params.dataStore);\n params.dataStore.addBytes32(Keys.WITHDRAWAL_LIST, withdrawalKey);\n WithdrawalEventUtils.emitWithdrawalCreated(\n params.eventEmitter,\n withdrawalKey,\n withdrawal,\n Withdrawal.WithdrawalType.Glv\n );\n\n Bank(payable(glvWithdrawal.glv())).transferOut(\n glvWithdrawal.market(),\n address(params.glvVault),\n marketTokenAmount\n );\n params.glvVault.syncTokenBalance(glvWithdrawal.market());\n\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams memory executeWithdrawalParams = IExecuteWithdrawalUtils\n .ExecuteWithdrawalParams({\n dataStore: params.dataStore,\n eventEmitter: params.eventEmitter,\n multichainVault: params.multichainVault,\n multichainTransferRouter: params.multichainTransferRouter,\n withdrawalVault: WithdrawalVault(payable(params.glvVault)),\n oracle: params.oracle,\n swapHandler: params.swapHandler,\n key: withdrawalKey,\n keeper: params.keeper,\n startingGas: params.startingGas,\n swapPricingType: ISwapPricingUtils.SwapPricingType.Withdrawal\n });\n\n return ExecuteWithdrawalUtils.executeWithdrawal(executeWithdrawalParams, withdrawal);\n }\n\n function _getMarketTokenAmount(\n DataStore dataStore,\n IOracle oracle,\n GlvWithdrawal.Props memory glvWithdrawal\n ) internal view returns (uint256) {\n uint256 glvValue = GlvUtils.getGlvValue(\n dataStore,\n oracle,\n glvWithdrawal.glv(),\n false // maximize\n );\n uint256 glvSupply = GlvToken(payable(glvWithdrawal.glv())).totalSupply();\n uint256 glvTokenUsd = GlvUtils.glvTokenAmountToUsd(glvWithdrawal.glvTokenAmount(), glvValue, glvSupply);\n\n Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, glvWithdrawal.market());\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n dataStore,\n market,\n oracle.getPrimaryPrice(market.indexToken),\n oracle.getPrimaryPrice(market.longToken),\n oracle.getPrimaryPrice(market.shortToken),\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n true // maximize\n );\n uint256 marketTokenAmount = MarketUtils.usdToMarketTokenAmount(\n glvTokenUsd,\n poolValueInfo.poolValue.toUint256(),\n ERC20(market.marketToken).totalSupply()\n );\n\n return marketTokenAmount;\n }\n\n function cancelGlvWithdrawal(CancelGlvWithdrawalParams memory params) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(params.dataStore, params.key);\n GlvWithdrawalStoreUtils.remove(params.dataStore, params.key, glvWithdrawal.account());\n\n if (glvWithdrawal.srcChainId() == 0) {\n params.glvVault.transferOut(\n glvWithdrawal.glv(),\n glvWithdrawal.account(),\n glvWithdrawal.glvTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n } else {\n params.glvVault.transferOut(\n glvWithdrawal.glv(),\n address(params.multichainVault),\n glvWithdrawal.glvTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n glvWithdrawal.glv(),\n glvWithdrawal.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n\n\n GlvWithdrawalEventUtils.emitGlvWithdrawalCancelled(\n params.eventEmitter,\n params.key,\n glvWithdrawal.account(),\n params.reason,\n params.reasonBytes\n );\n\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterGlvWithdrawalCancellation(params.key, glvWithdrawal, eventData);\n\n uint256 marketCount = GlvUtils.getGlvMarketCount(params.dataStore, glvWithdrawal.glv());\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.glvVault\n ),\n params.key,\n glvWithdrawal.callbackContract(),\n glvWithdrawal.executionFee(),\n params.startingGas,\n GasUtils.estimateGlvWithdrawalOraclePriceCount(\n marketCount,\n glvWithdrawal.longTokenSwapPath().length + glvWithdrawal.shortTokenSwapPath().length\n ),\n params.keeper,\n glvWithdrawal.receiver(),\n glvWithdrawal.srcChainId()\n );\n }\n}\n" + }, + "contracts/glv/glvWithdrawal/IGlvWithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IGlvWithdrawalUtils {\n struct CreateGlvWithdrawalParams {\n CreateGlvWithdrawalParamsAddresses addresses;\n uint256 minLongTokenAmount;\n uint256 minShortTokenAmount;\n bool shouldUnwrapNativeToken;\n uint256 executionFee;\n uint256 callbackGasLimit;\n bytes32[] dataList;\n }\n\n struct CreateGlvWithdrawalParamsAddresses {\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address glv;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n}\n" + }, + "contracts/gov/GovToken.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\";\n\nimport \"../chain/Chain.sol\";\nimport \"../role/RoleModule.sol\";\n\ncontract GovToken is ERC20, ERC20Permit, ERC20Votes, RoleModule {\n uint8 private _decimals;\n\n constructor(\n RoleStore roleStore_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n )\n ERC20(name_, symbol_)\n ERC20Permit(name_)\n RoleModule(roleStore_)\n {\n _decimals = decimals_;\n }\n\n function clock() public view override returns (uint48) {\n return SafeCast.toUint48(Chain.currentTimestamp());\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function CLOCK_MODE() public view override returns (string memory) {\n // Check that the clock was not modified\n require(clock() == Chain.currentTimestamp(), \"ERC20Votes: broken clock mode\");\n return \"mode=timestamp\";\n }\n\n function decimals() public view override returns (uint8) {\n return _decimals;\n }\n\n // @dev mint tokens to an account\n // @param account the account to mint to\n // @param amount the amount of tokens to mint\n function mint(address account, uint256 amount) external onlyGovTokenController {\n _mint(account, amount);\n }\n\n // @dev burn tokens from an account\n // @param account the account to burn tokens for\n // @param amount the amount of tokens to burn\n function burn(address account, uint256 amount) external onlyGovTokenController {\n _burn(account, amount);\n }\n\n function _transfer(address from, address to, uint256 amount) internal override {\n // only allow GOV_TOKEN_CONTROLLERs to make transfers\n // the user would need to approve the GOV_TOKEN_CONTROLLER contract\n // the GOV_TOKEN_CONTROLLER contract can then call transferFrom to transfer tokens\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \"GOV_TOKEN_CONTROLLER\");\n\n super._transfer(from, to, amount);\n }\n\n // The functions below are overrides required by Solidity.\n\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._afterTokenTransfer(from, to, amount);\n }\n\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" + }, + "contracts/liquidation/LiquidationUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../position/PositionStoreUtils.sol\";\nimport \"../order/OrderStoreUtils.sol\";\nimport \"../order/OrderEventUtils.sol\";\nimport \"../nonce/NonceUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\n\n// @title LiquidationUtils\n// @dev Library to help with liquidations\nlibrary LiquidationUtils {\n using Position for Position.Props;\n using Order for Order.Props;\n\n struct CreateLiquidationOrderCache {\n bytes32 positionKey;\n uint256 lastSrcChainId;\n }\n\n // @dev creates a liquidation order for a position\n // @param dataStore DataStore\n // @param account the position's account\n // @param market the position's market\n // @param collateralToken the position's collateralToken\n // @param isLong whether the position is long or short\n function createLiquidationOrder(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address market,\n address collateralToken,\n bool isLong\n ) external returns (bytes32) {\n CreateLiquidationOrderCache memory cache;\n\n cache.positionKey = Position.getPositionKey(account, market, collateralToken, isLong);\n Position.Props memory position = PositionStoreUtils.get(dataStore, cache.positionKey);\n\n Order.Addresses memory addresses = Order.Addresses(\n account, // account\n account, // receiver\n account, // cancellationReceiver\n CallbackUtils.getSavedCallbackContract(dataStore, account, market), // callbackContract\n address(0), // uiFeeReceiver\n market, // market\n position.collateralToken(), // initialCollateralToken\n new address[](0) // swapPath\n );\n\n cache.lastSrcChainId = dataStore.getUint(Keys.positionLastSrcChainId(cache.positionKey));\n\n // no slippage is set for this order, in case of a liquidation the amount\n // of collateral being swapped should not be too large\n // in case of large price impact, the user could be refunded\n // through a protocol fund if required, this amount could later be claimed\n // from the price impact pool, this claiming process should be added if\n // required\n //\n // setting a maximum price impact that will work for majority of cases\n // may also be challenging since the price impact would vary based on the\n // amount of collateral being swapped\n //\n // note that the decreasePositionSwapType should be SwapPnlTokenToCollateralToken\n // because fees are calculated with reference to the collateral token\n // fees are deducted from the output amount if the output token is the same as the\n // collateral token\n // swapping the pnl token to the collateral token helps to ensure fees can be paid\n // using the realized profit\n Order.Numbers memory numbers = Order.Numbers(\n Order.OrderType.Liquidation, // orderType\n Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken, // decreasePositionSwapType\n position.sizeInUsd(), // sizeDeltaUsd\n 0, // initialCollateralDeltaAmount\n 0, // triggerPrice\n position.isLong() ? 0 : type(uint256).max, // acceptablePrice\n 0, // executionFee\n dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT), // callbackGasLimit\n 0, // minOutputAmount\n Chain.currentTimestamp(), // updatedAtTime\n 0, // validFromTime\n cache.lastSrcChainId // srcChainId\n );\n\n Order.Flags memory flags = Order.Flags(\n position.isLong(), // isLong\n cache.lastSrcChainId == 0, // shouldUnwrapNativeToken\n false, // isFrozen\n false // autoCancel\n );\n\n Order.Props memory order = Order.Props(\n addresses,\n numbers,\n flags,\n new bytes32[](0)\n );\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n OrderStoreUtils.set(dataStore, key, order);\n\n OrderEventUtils.emitOrderCreated(eventEmitter, key, order);\n\n return key;\n }\n}\n" + }, + "contracts/market/Market.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title Market\n// @dev Struct for markets\n//\n// Markets support both spot and perp trading, they are created by specifying a\n// long collateral token, short collateral token and index token.\n//\n// Examples:\n//\n// - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH\n// - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC\n// - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL\n//\n// Liquidity providers can deposit either the long or short collateral token or\n// both to mint liquidity tokens.\n//\n// The long collateral token is used to back long positions, while the short\n// collateral token is used to back short positions.\n//\n// Liquidity providers take on the profits and losses of traders for the market\n// that they provide liquidity for.\n//\n// Having separate markets allows for risk isolation, liquidity providers are\n// only exposed to the markets that they deposit into, this potentially allow\n// for permissionless listings.\n//\n// Traders can use either the long or short token as collateral for the market.\nlibrary Market {\n // @param marketToken address of the market token for the market\n // @param indexToken address of the index token for the market\n // @param longToken address of the long token for the market\n // @param shortToken address of the short token for the market\n // @param data for any additional data\n struct Props {\n address marketToken;\n address indexToken;\n address longToken;\n address shortToken;\n }\n}\n" + }, + "contracts/market/MarketEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nimport \"./MarketPoolValueInfo.sol\";\n\nlibrary MarketEventUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // this event is emitted before a deposit or withdrawal\n // it provides information of the pool state so that the amount\n // of market tokens minted or amount withdrawn from the pool can be checked\n function emitMarketPoolValueInfo(\n EventEmitter eventEmitter,\n bytes32 tradeKey,\n address market,\n MarketPoolValueInfo.Props memory props,\n uint256 marketTokensSupply\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"tradeKey\", tradeKey);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.intItems.initItems(4);\n eventData.intItems.setItem(0, \"poolValue\", props.poolValue);\n eventData.intItems.setItem(1, \"longPnl\", props.longPnl);\n eventData.intItems.setItem(2, \"shortPnl\", props.shortPnl);\n eventData.intItems.setItem(3, \"netPnl\", props.netPnl);\n\n eventData.uintItems.initItems(8);\n eventData.uintItems.setItem(0, \"longTokenAmount\", props.longTokenAmount);\n eventData.uintItems.setItem(1, \"shortTokenAmount\", props.shortTokenAmount);\n eventData.uintItems.setItem(2, \"longTokenUsd\", props.longTokenUsd);\n eventData.uintItems.setItem(3, \"shortTokenUsd\", props.shortTokenUsd);\n eventData.uintItems.setItem(4, \"totalBorrowingFees\", props.totalBorrowingFees);\n eventData.uintItems.setItem(5, \"borrowingFeePoolFactor\", props.borrowingFeePoolFactor);\n eventData.uintItems.setItem(6, \"impactPoolAmount\", props.impactPoolAmount);\n eventData.uintItems.setItem(7, \"marketTokensSupply\", marketTokensSupply);\n\n eventEmitter.emitEventLog1(\n \"MarketPoolValueInfo\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n // this event is emitted after a deposit or withdrawal\n // it provides information of the updated pool state\n // note that the pool state can change even without a deposit / withdrawal\n // e.g. borrowing fees can increase the pool's value with time, trader pnl\n // will change as index prices change\n function emitMarketPoolValueUpdated(\n EventEmitter eventEmitter,\n bytes32 actionType,\n bytes32 tradeKey,\n address market,\n MarketPoolValueInfo.Props memory props,\n uint256 marketTokensSupply\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"actionType\", actionType);\n eventData.bytes32Items.setItem(1, \"tradeKey\", tradeKey);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.intItems.initItems(4);\n eventData.intItems.setItem(0, \"poolValue\", props.poolValue);\n eventData.intItems.setItem(1, \"longPnl\", props.longPnl);\n eventData.intItems.setItem(2, \"shortPnl\", props.shortPnl);\n eventData.intItems.setItem(3, \"netPnl\", props.netPnl);\n\n eventData.uintItems.initItems(8);\n eventData.uintItems.setItem(0, \"longTokenAmount\", props.longTokenAmount);\n eventData.uintItems.setItem(1, \"shortTokenAmount\", props.shortTokenAmount);\n eventData.uintItems.setItem(2, \"longTokenUsd\", props.longTokenUsd);\n eventData.uintItems.setItem(3, \"shortTokenUsd\", props.shortTokenUsd);\n eventData.uintItems.setItem(4, \"totalBorrowingFees\", props.totalBorrowingFees);\n eventData.uintItems.setItem(5, \"borrowingFeePoolFactor\", props.borrowingFeePoolFactor);\n eventData.uintItems.setItem(6, \"impactPoolAmount\", props.impactPoolAmount);\n eventData.uintItems.setItem(7, \"marketTokensSupply\", marketTokensSupply);\n\n eventEmitter.emitEventLog1(\n \"MarketPoolValueUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitPoolAmountUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"PoolAmountUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitSwapImpactPoolAmountUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"SwapImpactPoolAmountUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitPositionImpactPoolDistributed(\n EventEmitter eventEmitter,\n address market,\n uint256 distributionAmount,\n uint256 nextPositionImpactPoolAmount\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"distributionAmount\", distributionAmount);\n eventData.uintItems.setItem(1, \"nextPositionImpactPoolAmount\", nextPositionImpactPoolAmount);\n\n eventEmitter.emitEventLog1(\n \"PositionImpactPoolDistributed\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitTotalPendingImpactAmountUpdated(\n EventEmitter eventEmitter,\n address market,\n int256 delta,\n int256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.intItems.initItems(2);\n eventData.intItems.setItem(0, \"delta\", delta);\n eventData.intItems.setItem(1, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"TotalPendingImpactAmountUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitPositionImpactPoolAmountUpdated(\n EventEmitter eventEmitter,\n address market,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"PositionImpactPoolAmountUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitLentPositionImpactPoolAmountUpdated(\n EventEmitter eventEmitter,\n address market,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"LentPositionImpactPoolAmountUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitOpenInterestUpdated(\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"collateralToken\", collateralToken);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"OpenInterestUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitVirtualSwapInventoryUpdated(\n EventEmitter eventEmitter,\n address market,\n bool isLongToken,\n bytes32 virtualMarketId,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLongToken\", isLongToken);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"virtualMarketId\", virtualMarketId);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog2(\n \"VirtualSwapInventoryUpdated\",\n Cast.toBytes32(market),\n virtualMarketId,\n eventData\n );\n }\n\n function emitVirtualPositionInventoryUpdated(\n EventEmitter eventEmitter,\n address token,\n bytes32 virtualTokenId,\n int256 delta,\n int256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"token\", token);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"virtualTokenId\", virtualTokenId);\n\n eventData.intItems.initItems(2);\n eventData.intItems.setItem(0, \"delta\", delta);\n eventData.intItems.setItem(1, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog2(\n \"VirtualPositionInventoryUpdated\",\n Cast.toBytes32(token),\n virtualTokenId,\n eventData\n );\n }\n\n function emitOpenInterestInTokensUpdated(\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"collateralToken\", collateralToken);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"OpenInterestInTokensUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitCollateralSumUpdated(\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n int256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"collateralToken\", collateralToken);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"delta\", delta);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"CollateralSumUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitBorrowing(\n EventEmitter eventEmitter,\n address market,\n uint256 borrowingFactorPerSecond\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"borrowingFactorPerSecond\", borrowingFactorPerSecond);\n\n eventEmitter.emitEventLog1(\n \"Borrowing\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitBorrowingFactorUpdated(\n EventEmitter eventEmitter,\n address market,\n bool isLong,\n uint256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"CumulativeBorrowingFactorUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitFunding(\n EventEmitter eventEmitter,\n address market,\n uint256 fundingFactorPerSecond\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"market\", market);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"fundingFactorPerSecond\", fundingFactorPerSecond);\n\n eventEmitter.emitEventLog1(\n \"Funding\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitFundingFeeAmountPerSizeUpdated(\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n uint256 delta,\n uint256 value\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"collateralToken\", collateralToken);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"value\", value);\n\n eventEmitter.emitEventLog1(\n \"FundingFeeAmountPerSizeUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitClaimableFundingAmountPerSizeUpdated(\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n uint256 delta,\n uint256 value\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"collateralToken\", collateralToken);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", isLong);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"value\", value);\n\n eventEmitter.emitEventLog1(\n \"ClaimableFundingAmountPerSizeUpdated\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitClaimableFundingUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n address account,\n uint256 delta,\n uint256 nextValue,\n uint256 nextPoolValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"nextValue\", nextValue);\n eventData.uintItems.setItem(2, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog1(\n \"ClaimableFundingUpdated\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitFundingFeesClaimed(\n EventEmitter eventEmitter,\n address market,\n address token,\n address account,\n address receiver,\n uint256 amount,\n uint256 nextPoolValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(4);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n eventData.addressItems.setItem(3, \"receiver\", receiver);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventData.uintItems.setItem(1, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog1(\n \"FundingFeesClaimed\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitClaimableFundingUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n address account,\n uint256 delta,\n uint256 nextValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"timeKey\", timeKey);\n eventData.uintItems.setItem(1, \"delta\", delta);\n eventData.uintItems.setItem(2, \"nextValue\", nextValue);\n\n eventEmitter.emitEventLog1(\n \"ClaimableFundingUpdated\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitClaimableCollateralUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n address account,\n uint256 delta,\n uint256 nextValue,\n uint256 nextPoolValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n\n eventData.uintItems.initItems(4);\n eventData.uintItems.setItem(0, \"timeKey\", timeKey);\n eventData.uintItems.setItem(1, \"delta\", delta);\n eventData.uintItems.setItem(2, \"nextValue\", nextValue);\n eventData.uintItems.setItem(3, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog1(\n \"ClaimableCollateralUpdated\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitCollateralClaimed(\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n address account,\n address receiver,\n uint256 amount,\n uint256 nextPoolValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(4);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n eventData.addressItems.setItem(3, \"receiver\", receiver);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"timeKey\", timeKey);\n eventData.uintItems.setItem(1, \"amount\", amount);\n eventData.uintItems.setItem(2, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog1(\n \"CollateralClaimed\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitUiFeeFactorUpdated(\n EventEmitter eventEmitter,\n address account,\n uint256 uiFeeFactor\n ) external {\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"uiFeeFactor\", uiFeeFactor);\n\n eventEmitter.emitEventLog1(\n \"UiFeeFactorUpdated\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitPositionImpactPoolWithdrawal(\n EventEmitter eventEmitter,\n address market,\n address receiver,\n uint256 amount\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"receiver\", receiver);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n\n eventEmitter.emitEventLog1(\n \"PositionImpactPoolWithdrawal\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitLentImpactAmountReduction(\n EventEmitter eventEmitter,\n address market,\n address fundingAccount,\n uint256 longTokenAmount,\n uint256 shortTokenAmount,\n uint256 reductionAmount\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"fundingAccount\", fundingAccount);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"longTokenAmount\", longTokenAmount);\n eventData.uintItems.setItem(1, \"shortTokenAmount\", shortTokenAmount);\n eventData.uintItems.setItem(2, \"reductionAmount\", reductionAmount);\n\n eventEmitter.emitEventLog1(\n \"LentImpactAmountReduction\",\n Cast.toBytes32(market),\n eventData\n );\n }\n}\n" + }, + "contracts/market/MarketFactory.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./MarketToken.sol\";\nimport \"./Market.sol\";\nimport \"./MarketStoreUtils.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/Cast.sol\";\n\n// @title MarketFactory\n// @dev Contract to create markets\ncontract MarketFactory is RoleModule {\n using Market for Market.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n // @dev creates a market\n // @param indexToken address of the index token for the market\n // @param longToken address of the long token for the market\n // @param shortToken address of the short token for the market\n // @param marketType the type of the market\n function createMarket(\n address indexToken,\n address longToken,\n address shortToken,\n bytes32 marketType\n ) external onlyMarketKeeper returns (Market.Props memory) {\n bytes32 salt = keccak256(abi.encode(\n \"GMX_MARKET\",\n indexToken,\n longToken,\n shortToken,\n marketType\n ));\n\n address existingMarketAddress = dataStore.getAddress(MarketStoreUtils.getMarketSaltHash(salt));\n if (existingMarketAddress != address(0)) {\n revert Errors.MarketAlreadyExists(salt, existingMarketAddress);\n }\n\n MarketToken marketToken = new MarketToken{salt: salt}(roleStore, dataStore);\n\n // the marketType is not stored with the market, it is mainly used to ensure\n // markets with the same indexToken, longToken and shortToken can be created if needed\n Market.Props memory market = Market.Props(\n address(marketToken),\n indexToken,\n longToken,\n shortToken\n );\n\n MarketStoreUtils.set(dataStore, address(marketToken), salt, market);\n\n emitMarketCreated(address(marketToken), salt, indexToken, longToken, shortToken, marketType);\n\n return market;\n }\n\n function emitMarketCreated(\n address marketToken,\n bytes32 salt,\n address indexToken,\n address longToken,\n address shortToken,\n bytes32 marketType\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(4);\n eventData.addressItems.setItem(0, \"marketToken\", marketToken);\n eventData.addressItems.setItem(1, \"indexToken\", indexToken);\n eventData.addressItems.setItem(2, \"longToken\", longToken);\n eventData.addressItems.setItem(3, \"shortToken\", shortToken);\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"salt\", salt);\n eventData.bytes32Items.setItem(1, \"marketType\", marketType);\n\n eventEmitter.emitEventLog1(\n \"MarketCreated\",\n Cast.toBytes32(marketToken),\n eventData\n );\n }\n}\n" + }, + "contracts/market/MarketPoolValueInfo.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title MarketPoolInfo\nlibrary MarketPoolValueInfo {\n // @dev struct to avoid stack too deep errors for the getPoolValue call\n // @param poolValue the value of the pool in USD\n // @param longPnl the pending pnl of long positions\n // @param shortPnl the pending pnl of short positions\n // @param netPnl the net pnl of long and short positions\n // @param longTokenAmount the amount of long token in the pool\n // @param shortTokenAmount the amount of short token in the pool\n // @param longTokenUsd the USD value of the long tokens in the pool\n // @param shortTokenUsd the USD value of the short tokens in the pool\n // @param totalBorrowingFees the total pending borrowing fees for the market\n // @param borrowingFeePoolFactor the pool factor for borrowing fees\n // @param impactPoolAmount the amount of tokens in the impact pool\n // @param lentImpactPoolAmount the amount lent if impact pool is less than the positive price impact\n struct Props {\n int256 poolValue;\n int256 longPnl;\n int256 shortPnl;\n int256 netPnl;\n\n uint256 longTokenAmount;\n uint256 shortTokenAmount;\n uint256 longTokenUsd;\n uint256 shortTokenUsd;\n\n uint256 totalBorrowingFees;\n uint256 borrowingFeePoolFactor;\n\n uint256 impactPoolAmount;\n uint256 lentImpactPoolAmount;\n }\n}\n" + }, + "contracts/market/MarketStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Market.sol\";\n\n/**\n * @title MarketStoreUtils\n * @dev Library for market storage functions\n */\nlibrary MarketStoreUtils {\n using Market for Market.Props;\n\n bytes32 public constant MARKET_SALT = keccak256(abi.encode(\"MARKET_SALT\"));\n bytes32 public constant MARKET_KEY = keccak256(abi.encode(\"MARKET_KEY\"));\n bytes32 public constant MARKET_TOKEN = keccak256(abi.encode(\"MARKET_TOKEN\"));\n bytes32 public constant INDEX_TOKEN = keccak256(abi.encode(\"INDEX_TOKEN\"));\n bytes32 public constant LONG_TOKEN = keccak256(abi.encode(\"LONG_TOKEN\"));\n bytes32 public constant SHORT_TOKEN = keccak256(abi.encode(\"SHORT_TOKEN\"));\n\n function get(DataStore dataStore, address key) public view returns (Market.Props memory) {\n Market.Props memory market;\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\n return market;\n }\n\n market.marketToken = dataStore.getAddress(\n keccak256(abi.encode(key, MARKET_TOKEN))\n );\n\n market.indexToken = dataStore.getAddress(\n keccak256(abi.encode(key, INDEX_TOKEN))\n );\n\n market.longToken = dataStore.getAddress(\n keccak256(abi.encode(key, LONG_TOKEN))\n );\n\n market.shortToken = dataStore.getAddress(\n keccak256(abi.encode(key, SHORT_TOKEN))\n );\n\n return market;\n }\n\n function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\n address key = dataStore.getAddress(getMarketSaltHash(salt));\n return get(dataStore, key);\n }\n\n function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\n dataStore.addAddress(\n Keys.MARKET_LIST,\n key\n );\n\n // the salt is based on the market props while the key gives the market's address\n // use the salt to store a reference to the key to allow the key to be retrieved\n // using just the salt value\n dataStore.setAddress(\n getMarketSaltHash(salt),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET_TOKEN)),\n market.marketToken\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, INDEX_TOKEN)),\n market.indexToken\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, LONG_TOKEN)),\n market.longToken\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, SHORT_TOKEN)),\n market.shortToken\n );\n }\n\n function remove(DataStore dataStore, address key, bytes32 salt) external {\n if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {\n revert Errors.MarketNotFound(key);\n }\n\n dataStore.removeAddress(\n Keys.MARKET_LIST,\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, INDEX_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, LONG_TOKEN))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, SHORT_TOKEN))\n );\n\n dataStore.removeAddress(\n getMarketSaltHash(salt)\n );\n }\n\n function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {\n return keccak256(abi.encode(MARKET_SALT, salt));\n }\n\n function getMarketCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getAddressCount(Keys.MARKET_LIST);\n }\n\n function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {\n return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);\n }\n}\n" + }, + "contracts/market/MarketToken.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../bank/Bank.sol\";\n\n// @title MarketToken\n// @dev The market token for a market, stores funds for the market and keeps track\n// of the liquidity owners\ncontract MarketToken is ERC20, Bank {\n constructor(RoleStore _roleStore, DataStore _dataStore) ERC20(\"GMX Market\", \"GM\") Bank(_roleStore, _dataStore) {\n }\n\n // @dev mint market tokens to an account\n // @param account the account to mint to\n // @param amount the amount of tokens to mint\n function mint(address account, uint256 amount) external onlyController {\n _mint(account, amount);\n }\n\n // @dev burn market tokens from an account\n // @param account the account to burn tokens for\n // @param amount the amount of tokens to burn\n function burn(address account, uint256 amount) external onlyController {\n _burn(account, amount);\n }\n}\n" + }, + "contracts/market/MarketUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"./Market.sol\";\nimport \"./MarketPoolValueInfo.sol\";\nimport \"./MarketToken.sol\";\nimport \"./MarketEventUtils.sol\";\nimport \"./MarketStoreUtils.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../order/Order.sol\";\n\nimport \"../oracle/IOracle.sol\";\nimport \"../price/Price.sol\";\n\nimport \"../utils/Calc.sol\";\nimport \"../utils/Precision.sol\";\n\nimport \"../feature/FeatureUtils.sol\";\n\n// @title MarketUtils\n// @dev Library for market functions\nlibrary MarketUtils {\n using SignedMath for int256;\n using SafeCast for int256;\n using SafeCast for uint256;\n\n using Market for Market.Props;\n using Position for Position.Props;\n using Order for Order.Props;\n using Price for Price.Props;\n\n enum FundingRateChangeType {\n NoChange,\n Increase,\n Decrease\n }\n\n // @dev struct to store the prices of tokens of a market\n // @param indexTokenPrice price of the market's index token\n // @param longTokenPrice price of the market's long token\n // @param shortTokenPrice price of the market's short token\n struct MarketPrices {\n Price.Props indexTokenPrice;\n Price.Props longTokenPrice;\n Price.Props shortTokenPrice;\n }\n\n struct CollateralType {\n uint256 longToken;\n uint256 shortToken;\n }\n\n struct PositionType {\n CollateralType long;\n CollateralType short;\n }\n\n // @dev struct for the result of the getNextFundingAmountPerSize call\n // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond\n // see getNextFundingFactorPerSecond for more info\n struct GetNextFundingAmountPerSizeResult {\n bool longsPayShorts;\n uint256 fundingFactorPerSecond;\n int256 nextSavedFundingFactorPerSecond;\n\n PositionType fundingFeeAmountPerSizeDelta;\n PositionType claimableFundingAmountPerSizeDelta;\n }\n\n struct GetNextFundingAmountPerSizeCache {\n PositionType openInterest;\n\n uint256 longOpenInterest;\n uint256 shortOpenInterest;\n\n uint256 durationInSeconds;\n\n uint256 sizeOfPayingSide;\n uint256 fundingUsd;\n\n uint256 fundingUsdForLongCollateral;\n uint256 fundingUsdForShortCollateral;\n }\n\n struct GetNextFundingFactorPerSecondCache {\n uint256 diffUsd;\n uint256 totalOpenInterest;\n\n uint256 fundingFactor;\n uint256 fundingExponentFactor;\n\n uint256 diffUsdAfterExponent;\n uint256 diffUsdToOpenInterestFactor;\n\n int256 savedFundingFactorPerSecond;\n uint256 savedFundingFactorPerSecondMagnitude;\n\n int256 nextSavedFundingFactorPerSecond;\n int256 nextSavedFundingFactorPerSecondWithMinBound;\n }\n\n struct FundingConfigCache {\n uint256 thresholdForStableFunding;\n uint256 thresholdForDecreaseFunding;\n\n uint256 fundingIncreaseFactorPerSecond;\n uint256 fundingDecreaseFactorPerSecond;\n\n uint256 minFundingFactorPerSecond;\n uint256 maxFundingFactorPerSecond;\n }\n\n struct GetExpectedMinTokenBalanceCache {\n uint256 poolAmount;\n uint256 swapImpactPoolAmount;\n uint256 claimableCollateralAmount;\n uint256 claimableFeeAmount;\n uint256 claimableUiFeeAmount;\n uint256 affiliateRewardAmount;\n }\n\n struct ApplyDeltaToPositionImpactPoolCache {\n bytes32 positionImpactPoolAmountKey;\n bytes32 lentPositionImpactPoolAmountKey;\n uint256 deltaMagnitude;\n uint256 poolAmount;\n uint256 excessAmount;\n uint256 nextValue;\n }\n\n struct CapPositiveImpactUsdByPositionImpactPoolCache {\n uint256 impactPoolAmount;\n uint256 impactPoolUsd;\n uint256 lentAmount;\n uint256 longTokenUsd;\n uint256 shortTokenUsd;\n uint256 maxLendableUsd;\n uint256 maxPriceImpactUsd;\n uint256 usdRequiredToBeLent;\n }\n\n // @dev get the market token's price\n // @param dataStore DataStore\n // @param market the market to check\n // @param longTokenPrice the price of the long token\n // @param shortTokenPrice the price of the short token\n // @param indexTokenPrice the price of the index token\n // @param maximize whether to maximize or minimize the market token price\n // @return returns (the market token's price, MarketPoolValueInfo.Props)\n function getMarketTokenPrice(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n bytes32 pnlFactorType,\n bool maximize\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\n uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));\n\n MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(\n dataStore,\n market,\n indexTokenPrice,\n longTokenPrice,\n shortTokenPrice,\n pnlFactorType,\n maximize\n );\n\n // if the supply is zero then treat the market token price as 1 USD\n if (supply == 0) {\n return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);\n }\n\n if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }\n\n int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);\n return (marketTokenPrice, poolValueInfo);\n }\n\n // @dev get the total supply of the marketToken\n // @param marketToken the marketToken\n // @return the total supply of the marketToken\n function getMarketTokenSupply(MarketToken marketToken) public view returns (uint256) {\n return marketToken.totalSupply();\n }\n\n // @dev get the opposite token of the market\n // if the inputToken is the longToken return the shortToken and vice versa\n // @param inputToken the input token\n // @param market the market values\n // @return the opposite token\n function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {\n if (inputToken == market.longToken) {\n return market.shortToken;\n }\n\n if (inputToken == market.shortToken) {\n return market.longToken;\n }\n\n revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);\n }\n\n function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n validateSwapMarket(dataStore, market);\n }\n\n function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {\n validateEnabledMarket(dataStore, market);\n\n if (market.longToken == market.shortToken) {\n revert Errors.InvalidSwapMarket(market.marketToken);\n }\n }\n\n // @dev get the token price from the stored MarketPrices\n // @param token the token to get the price for\n // @param the market values\n // @param the market token prices\n // @return the token price from the stored MarketPrices\n function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {\n if (token == market.longToken) {\n return prices.longTokenPrice;\n }\n if (token == market.shortToken) {\n return prices.shortTokenPrice;\n }\n if (token == market.indexToken) {\n return prices.indexTokenPrice;\n }\n\n revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);\n }\n\n // @dev return the primary prices for the market tokens\n // @param oracle Oracle\n // @param market the market values\n function getMarketPrices(IOracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {\n return MarketPrices(\n oracle.getPrimaryPrice(market.indexToken),\n oracle.getPrimaryPrice(market.longToken),\n oracle.getPrimaryPrice(market.shortToken)\n );\n }\n\n // @dev get the usd value of either the long or short tokens in the pool\n // without accounting for the pnl of open positions\n // @param dataStore DataStore\n // @param market the market values\n // @param prices the prices of the market tokens\n // @param whether to return the value for the long or short token\n // @return the usd value of either the long or short tokens in the pool\n function getPoolUsdWithoutPnl(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong,\n bool maximize\n ) internal view returns (uint256) {\n address token = isLong ? market.longToken : market.shortToken;\n // note that if it is a single token market, the poolAmount returned will be\n // the amount of tokens in the pool divided by 2\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\n uint256 tokenPrice;\n\n if (maximize) {\n tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;\n } else {\n tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\n }\n\n return poolAmount * tokenPrice;\n }\n\n // @dev get the USD value of a pool\n // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl\n // we use the token index prices to calculate this and ignore price impact since if all positions were closed the\n // net price impact should be zero\n // note that there is exposure to the index token through the positionImpactPoolAmount and lentPositionImpactPoolAmount\n // if these amounts are large they may be a significant contributor to the GM token price\n // @param dataStore DataStore\n // @param market the market values\n // @param longTokenPrice price of the long token\n // @param shortTokenPrice price of the short token\n // @param indexTokenPrice price of the index token\n // @param maximize whether to maximize or minimize the pool value\n // @return the value information of a pool\n function getPoolValueInfo(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n bytes32 pnlFactorType,\n bool maximize\n ) public view returns (MarketPoolValueInfo.Props memory) {\n MarketPoolValueInfo.Props memory result;\n\n result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);\n result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);\n\n result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);\n result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);\n\n result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();\n\n MarketPrices memory prices = MarketPrices(\n indexTokenPrice,\n longTokenPrice,\n shortTokenPrice\n );\n\n result.totalBorrowingFees = getTotalPendingBorrowingFees(\n dataStore,\n market,\n prices,\n true\n );\n\n result.totalBorrowingFees += getTotalPendingBorrowingFees(\n dataStore,\n market,\n prices,\n false\n );\n\n result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\n result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();\n\n // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value\n // and a smaller pnl leads to a larger pool value\n //\n // while positions will always be closed at the less favourable price\n // using the inverse of maximize for the getPnl calls would help prevent\n // gaming of market token values by increasing the spread\n //\n // liquidations could be triggered by manipulating a large spread but\n // that should be more difficult to execute\n\n result.longPnl = getPnl(\n dataStore,\n market,\n indexTokenPrice,\n true, // isLong\n !maximize // maximize\n );\n\n result.longPnl = getCappedPnl(\n dataStore,\n market.marketToken,\n true,\n result.longPnl,\n result.longTokenUsd,\n pnlFactorType\n );\n\n result.shortPnl = getPnl(\n dataStore,\n market,\n indexTokenPrice,\n false, // isLong\n !maximize // maximize\n );\n\n result.shortPnl = getCappedPnl(\n dataStore,\n market.marketToken,\n false,\n result.shortPnl,\n result.shortTokenUsd,\n pnlFactorType\n );\n\n result.netPnl = result.longPnl + result.shortPnl;\n result.poolValue = result.poolValue - result.netPnl;\n\n result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);\n // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue\n uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);\n\n result.poolValue -= impactPoolUsd.toInt256();\n\n result.lentImpactPoolAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\n // use maximize for pickPrice since the lentImpactPoolUsd is added to the poolValue\n uint256 lentImpactPoolUsd = result.lentImpactPoolAmount * indexTokenPrice.pickPrice(maximize);\n\n result.poolValue += lentImpactPoolUsd.toInt256();\n\n return result;\n }\n\n // @dev get the net pending pnl for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param indexTokenPrice the price of the index token\n // @param maximize whether to maximize or minimize the net pnl\n // @return the net pending pnl for a market\n function getNetPnl(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n bool maximize\n ) internal view returns (int256) {\n int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);\n int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);\n\n return longPnl + shortPnl;\n }\n\n // @dev get the capped pending pnl for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check for the long or short side\n // @param pnl the uncapped pnl of the market\n // @param poolUsd the USD value of the pool\n // @param pnlFactorType the pnl factor type to use\n function getCappedPnl(\n DataStore dataStore,\n address market,\n bool isLong,\n int256 pnl,\n uint256 poolUsd,\n bytes32 pnlFactorType\n ) internal view returns (int256) {\n if (pnl < 0) { return pnl; }\n\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);\n int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();\n\n return pnl > maxPnl ? maxPnl : pnl;\n }\n\n // @dev get the pending pnl for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param indexTokenPrice the price of the index token\n // @param isLong whether to check for the long or short side\n // @param maximize whether to maximize or minimize the pnl\n function getPnl(\n DataStore dataStore,\n Market.Props memory market,\n uint256 indexTokenPrice,\n bool isLong,\n bool maximize\n ) internal view returns (int256) {\n Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);\n\n return getPnl(\n dataStore,\n market,\n _indexTokenPrice,\n isLong,\n maximize\n );\n }\n\n // @dev get the pending pnl for a market for either longs or shorts\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param indexTokenPrice the price of the index token\n // @param isLong whether to get the pnl for longs or shorts\n // @param maximize whether to maximize or minimize the net pnl\n // @return the pending pnl for a market for either longs or shorts\n function getPnl(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n bool isLong,\n bool maximize\n ) internal view returns (int256) {\n int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\n if (openInterest == 0 || openInterestInTokens == 0) {\n return 0;\n }\n\n uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);\n\n // openInterest is the cost of all positions, openInterestValue is the current worth of all positions\n int256 openInterestValue = (openInterestInTokens * price).toInt256();\n int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;\n\n return pnl;\n }\n\n // @dev get the amount of tokens in the pool\n // @param dataStore DataStore\n // @param market the market to check\n // @param token the token to check\n // @return the amount of tokens in the pool\n function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {\n /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */\n // if the longToken and shortToken are the same, return half of the token amount, so that\n // calculations of pool value, etc would be correct\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\n return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;\n }\n\n // @dev get the max amount of tokens allowed to be in the pool\n // @param dataStore DataStore\n // @param market the market to check\n // @param token the token to check\n // @return the max amount of tokens that are allowed in the pool\n function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\n return dataStore.getUint(Keys.maxPoolAmountKey(market, token));\n }\n\n function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {\n return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));\n }\n\n function getUsageFactor(\n DataStore dataStore,\n Market.Props memory market,\n bool isLong,\n uint256 reservedUsd,\n uint256 poolUsd\n ) internal view returns (uint256) {\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\n uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);\n\n return reserveUsageFactor;\n }\n\n // @dev get the max open interest allowed for the market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether this is for the long or short side\n // @return the max open interest allowed for the market\n function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));\n }\n\n // @dev increment the claimable collateral amount\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to increment the claimable collateral for\n // @param token the claimable token\n // @param account the account to increment the claimable collateral for\n // @param delta the amount to increment\n function incrementClaimableCollateralAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n address account,\n uint256 delta\n ) internal {\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\n uint256 timeKey = Chain.currentTimestamp() / divisor;\n\n uint256 nextValue = dataStore.incrementUint(\n Keys.claimableCollateralAmountKey(market, token, timeKey, account),\n delta\n );\n\n uint256 nextPoolValue = dataStore.incrementUint(\n Keys.claimableCollateralAmountKey(market, token),\n delta\n );\n\n MarketEventUtils.emitClaimableCollateralUpdated(\n eventEmitter,\n market,\n token,\n timeKey,\n account,\n delta,\n nextValue,\n nextPoolValue\n );\n }\n\n // @dev increment the claimable funding amount\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the trading market\n // @param token the claimable token\n // @param account the account to increment for\n // @param delta the amount to increment\n function incrementClaimableFundingAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n address account,\n uint256 delta\n ) internal {\n uint256 nextValue = dataStore.incrementUint(\n Keys.claimableFundingAmountKey(market, token, account),\n delta\n );\n\n uint256 nextPoolValue = dataStore.incrementUint(\n Keys.claimableFundingAmountKey(market, token),\n delta\n );\n\n MarketEventUtils.emitClaimableFundingUpdated(\n eventEmitter,\n market,\n token,\n account,\n delta,\n nextValue,\n nextPoolValue\n );\n }\n\n // @dev claim funding fees\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to claim for\n // @param token the token to claim\n // @param account the account to claim for\n // @param receiver the receiver to send the amount to\n function claimFundingFees(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n address account,\n address receiver\n ) internal returns (uint256) {\n bytes32 key = Keys.claimableFundingAmountKey(market, token, account);\n\n uint256 claimableAmount = dataStore.getUint(key);\n dataStore.setUint(key, 0);\n\n uint256 nextPoolValue = dataStore.decrementUint(\n Keys.claimableFundingAmountKey(market, token),\n claimableAmount\n );\n\n MarketToken(payable(market)).transferOut(\n token,\n receiver,\n claimableAmount\n );\n\n validateMarketTokenBalance(dataStore, market);\n\n MarketEventUtils.emitFundingFeesClaimed(\n eventEmitter,\n market,\n token,\n account,\n receiver,\n claimableAmount,\n nextPoolValue\n );\n\n return claimableAmount;\n }\n\n function batchClaimCollateral(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address[] memory markets,\n address[] memory tokens,\n uint256[] memory timeKeys,\n address receiver,\n address account\n ) internal returns (uint256[] memory) {\n if (markets.length != tokens.length || tokens.length != timeKeys.length) {\n revert Errors.InvalidClaimCollateralInput(markets.length, tokens.length, timeKeys.length);\n }\n\n FeatureUtils.validateFeature(dataStore, Keys.claimCollateralFeatureDisabledKey(address(this)));\n\n AccountUtils.validateReceiver(receiver);\n\n uint256[] memory claimedAmounts = new uint256[](markets.length);\n\n for (uint256 i; i < markets.length; i++) {\n claimedAmounts[i] = MarketUtils.claimCollateral(\n dataStore,\n eventEmitter,\n markets[i],\n tokens[i],\n timeKeys[i],\n account,\n receiver\n );\n }\n\n return claimedAmounts;\n }\n\n // @dev claim collateral\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to claim for\n // @param token the token to claim\n // @param timeKey the time key\n // @param account the account to claim for\n // @param receiver the receiver to send the amount to\n function claimCollateral(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 timeKey,\n address account,\n address receiver\n ) internal returns (uint256) {\n uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));\n\n uint256 claimableFactor = _getClaimableFactor(dataStore, market, token, timeKey, account);\n\n if (claimableFactor > Precision.FLOAT_PRECISION) {\n revert Errors.InvalidClaimableFactor(claimableFactor);\n }\n\n uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));\n\n uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);\n if (adjustedClaimableAmount <= claimedAmount) {\n revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);\n }\n\n uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;\n\n dataStore.setUint(\n Keys.claimedCollateralAmountKey(market, token, timeKey, account),\n adjustedClaimableAmount\n );\n\n uint256 nextPoolValue = dataStore.decrementUint(\n Keys.claimableCollateralAmountKey(market, token),\n amountToBeClaimed\n );\n\n MarketToken(payable(market)).transferOut(\n token,\n receiver,\n amountToBeClaimed\n );\n\n validateMarketTokenBalance(dataStore, market);\n\n MarketEventUtils.emitCollateralClaimed(\n eventEmitter,\n market,\n token,\n timeKey,\n account,\n receiver,\n amountToBeClaimed,\n nextPoolValue\n );\n\n return amountToBeClaimed;\n }\n\n function _getClaimableFactor(\n DataStore dataStore,\n address market,\n address token,\n uint256 timeKey,\n address account\n ) internal view returns (uint256) {\n uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));\n uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));\n uint256 claimableFactor = claimableFactorForTime > claimableFactorForAccount\n ? claimableFactorForTime\n : claimableFactorForAccount;\n\n // if the divisor is changed the timeDiff calculation would no longer be accurate\n uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);\n\n uint256 claimableReductionFactor = dataStore.getUint(Keys.claimableCollateralReductionFactorKey(market, token, timeKey, account));\n uint256 timeDiff = Chain.currentTimestamp() - timeKey * divisor;\n uint256 claimableCollateralDelay = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_DELAY);\n\n if (claimableFactor == 0 && claimableReductionFactor == 0 && timeDiff > claimableCollateralDelay) {\n claimableFactor = Precision.FLOAT_PRECISION;\n }\n\n if (claimableFactor > claimableReductionFactor) {\n claimableFactor -= claimableReductionFactor;\n } else {\n claimableFactor = 0;\n }\n\n return claimableFactor;\n }\n\n // @dev apply a delta to the pool amount\n // validatePoolAmount is not called in this function since applyDeltaToPoolAmount\n // is called when receiving fees\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param token the token to apply to\n // @param delta the delta amount\n function applyDeltaToPoolAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Market.Props memory market,\n address token,\n int256 delta\n ) internal returns (uint256) {\n uint256 nextValue = dataStore.applyDeltaToUint(\n Keys.poolAmountKey(market.marketToken, token),\n delta,\n \"Invalid state, negative poolAmount\"\n );\n\n applyDeltaToVirtualInventoryForSwaps(\n dataStore,\n eventEmitter,\n market,\n token,\n delta\n );\n\n MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);\n\n return nextValue;\n }\n\n function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);\n\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\n }\n\n function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\n uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));\n uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));\n\n // if the positive impact factor is more than the negative impact factor, positions could be opened\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\n if (positiveImpactFactor > negativeImpactFactor) {\n positiveImpactFactor = negativeImpactFactor;\n }\n\n return (positiveImpactFactor, negativeImpactFactor);\n }\n\n function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);\n\n return isPositive ? positiveImpactFactor : negativeImpactFactor;\n }\n\n function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\n uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));\n uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));\n\n // if the positive impact factor is more than the negative impact factor, positions could be opened\n // and closed immediately for a profit if the difference is sufficient to cover the position fees\n if (positiveImpactFactor > negativeImpactFactor) {\n positiveImpactFactor = negativeImpactFactor;\n }\n\n return (positiveImpactFactor, negativeImpactFactor);\n }\n\n // @dev cap the input priceImpactUsd by the available amount in the\n // position impact pool\n // Note that since the price impact can be capped, a malicious\n // CONFIG_KEEPER can set price impact values to be very large\n // then make trades to incur a large amount of negative price impact\n // in account A, and a large amount of positive price impact in\n // account B\n // since the price impact in account A is claimable, and the positive\n // price impact in account B is first paid for by the pool, this method\n // can be used to reduce the funds in the GM pool\n // the CLAIMABLE_COLLATERAL_DELAY should be restricted to be at least\n // 24 hours or more to allow for activity of this form to be blocked\n // @param dataStore DataStore\n // @param market the trading market\n // @param indexTokenPrice the price of the token\n // @param priceImpactUsd the calculated USD price impact\n // @return the capped priceImpactUsd\n function capPositiveImpactUsdByPositionImpactPool(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n int256 priceImpactUsd\n ) internal view returns (int256) {\n if (priceImpactUsd <= 0) {\n return priceImpactUsd;\n }\n\n CapPositiveImpactUsdByPositionImpactPoolCache memory cache;\n\n cache.impactPoolAmount = getPositionImpactPoolAmount(dataStore, market.marketToken);\n\n // the totalPendingImpactAmount is not factored into the capping here\n // we assume that the ratio of negative impact to positive impact and\n // ratio of negative impact cap to positive impact cap is such that the\n // total negative impact will be more than the positive impact for\n // majority of the time\n // additionally, since there is capping of price impact, the\n // totalPendingImpactAmount would not give an accurate representation\n // of the actual price impact that would be realised\n cache.impactPoolUsd = cache.impactPoolAmount * prices.indexTokenPrice.min;\n\n // if priceImpactUsd > impactPoolUsd, calculate the usdRequiredToBeLent\n // otherwise, the impactPoolUsd is sufficient and priceImpactUsd does not\n // need to be capped here\n if (priceImpactUsd.toUint256() > cache.impactPoolUsd) {\n cache.usdRequiredToBeLent = priceImpactUsd.toUint256() - cache.impactPoolUsd;\n }\n\n // if usdRequiredToBeLent > 0, check how much is lendable\n if (cache.usdRequiredToBeLent > 0) {\n cache.lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\n // capping the max lendable amount to a factor of the pool amount is mainly a sanity check to prevent\n // the lent amount from being too large relative to the amounts in the pool\n // trader pnl, borrowing fees, etc is not factored into this calculation\n cache.longTokenUsd = getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\n cache.shortTokenUsd = getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\n\n cache.maxLendableUsd = getMaxLendableUsdAvailable(\n dataStore,\n market.marketToken,\n cache.longTokenUsd + cache.shortTokenUsd,\n prices.indexTokenPrice.max,\n cache.lentAmount\n );\n\n // if usdRequiredToBeLent > maxLendableUsd, then cap the price impact to impactPoolUsd + maxLendableUsd\n if (cache.usdRequiredToBeLent > cache.maxLendableUsd) {\n priceImpactUsd = cache.impactPoolUsd.toInt256() + cache.maxLendableUsd.toInt256();\n }\n }\n\n return priceImpactUsd;\n }\n\n function getMaxLendableUsdAvailable(\n DataStore dataStore,\n address market,\n uint256 poolUsd,\n uint256 indexTokenPrice,\n uint256 lentAmount\n ) internal view returns (uint256) {\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorKey(market));\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\n\n uint256 maxLendableUsdConfig = dataStore.getUint(Keys.maxLendableImpactUsdKey(market));\n if (maxLendableUsd > maxLendableUsdConfig) {\n maxLendableUsd = maxLendableUsdConfig;\n }\n\n uint256 lentUsd = lentAmount * indexTokenPrice;\n\n if (lentUsd > maxLendableUsd) {\n return 0;\n }\n\n return maxLendableUsd - lentUsd;\n }\n\n // @dev cap the input priceImpactUsd by the max positive position impact factor\n // @param dataStore DataStore\n // @param market the trading market\n // @param priceImpactUsd the calculated USD price impact\n // @param sizeDeltaUsd the size by which the position is increased/decreased\n // @return the capped priceImpactUsd\n function capPositiveImpactUsdByMaxPositionImpact(\n DataStore dataStore,\n address market,\n int256 priceImpactUsd,\n uint256 sizeDeltaUsd\n ) internal view returns (int256) {\n if (priceImpactUsd < 0) {\n return priceImpactUsd;\n }\n\n uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);\n int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();\n\n // capped by the positive price impact\n if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {\n priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;\n }\n\n return priceImpactUsd;\n }\n\n function getTotalPendingImpactAmount(DataStore dataStore, address market) internal view returns (int256) {\n return dataStore.getInt(Keys.totalPendingImpactAmountKey(market));\n }\n\n // @dev get the position impact pool amount\n // @param dataStore DataStore\n // @param market the market to check\n // @return the position impact pool amount\n function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {\n return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));\n }\n\n // @dev get the swap impact pool amount\n // @param dataStore DataStore\n // @param market the market to check\n // @param token the token to check\n // @return the swap impact pool amount\n function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {\n return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));\n }\n\n // @dev apply a delta to the swap impact pool\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param token the token to apply to\n // @param delta the delta amount\n function applyDeltaToSwapImpactPool(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n int256 delta\n ) internal returns (uint256) {\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\n Keys.swapImpactPoolAmountKey(market, token),\n delta\n );\n\n MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);\n\n return nextValue;\n }\n\n function applyDeltaToTotalPendingImpactAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n int256 delta\n ) internal returns (int256) {\n int256 nextValue = dataStore.applyDeltaToInt(\n Keys.totalPendingImpactAmountKey(market),\n delta\n );\n\n MarketEventUtils.emitTotalPendingImpactAmountUpdated(\n eventEmitter,\n market,\n delta,\n nextValue\n );\n\n return nextValue;\n }\n\n // @dev apply a delta to the position impact pool\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param delta the delta amount\n function applyDeltaToPositionImpactPool(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n int256 delta\n ) internal {\n ApplyDeltaToPositionImpactPoolCache memory cache;\n cache.deltaMagnitude = delta.abs();\n\n if (delta < 0) {\n cache.positionImpactPoolAmountKey = Keys.positionImpactPoolAmountKey(market);\n cache.poolAmount = dataStore.getUint(cache.positionImpactPoolAmountKey);\n\n if (cache.deltaMagnitude > cache.poolAmount) {\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\n\n dataStore.setUint(cache.positionImpactPoolAmountKey, 0);\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\n\n cache.nextValue = dataStore.incrementUint(Keys.lentPositionImpactPoolAmountKey(market), cache.excessAmount);\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\n } else {\n cache.nextValue = dataStore.decrementUint(cache.positionImpactPoolAmountKey, cache.deltaMagnitude);\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\n }\n } else {\n cache.lentPositionImpactPoolAmountKey = Keys.lentPositionImpactPoolAmountKey(market);\n cache.poolAmount = dataStore.getUint(cache.lentPositionImpactPoolAmountKey);\n\n if (cache.deltaMagnitude > cache.poolAmount) {\n cache.excessAmount = cache.deltaMagnitude - cache.poolAmount;\n\n dataStore.setUint(cache.lentPositionImpactPoolAmountKey, 0);\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, cache.poolAmount.toInt256(), 0);\n\n cache.nextValue = dataStore.incrementUint(Keys.positionImpactPoolAmountKey(market), cache.excessAmount);\n MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, cache.excessAmount.toInt256(), cache.nextValue);\n } else {\n cache.nextValue = dataStore.decrementUint(cache.lentPositionImpactPoolAmountKey, cache.deltaMagnitude);\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, delta, cache.nextValue);\n }\n }\n }\n\n // @dev apply a delta to the open interest\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param collateralToken the collateralToken to apply to\n // @param isLong whether to apply to the long or short side\n // @param delta the delta amount\n function applyDeltaToOpenInterest(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Market.Props memory market,\n address collateralToken,\n bool isLong,\n int256 delta\n ) internal returns (uint256) {\n if (market.indexToken == address(0)) {\n revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);\n }\n\n uint256 nextValue = dataStore.applyDeltaToUint(\n Keys.openInterestKey(market.marketToken, collateralToken, isLong),\n delta,\n \"Invalid state: negative open interest\"\n );\n\n // if the open interest for longs is increased then tokens were virtually bought from the pool\n // so the virtual inventory should be decreased\n // if the open interest for longs is decreased then tokens were virtually sold to the pool\n // so the virtual inventory should be increased\n // if the open interest for shorts is increased then tokens were virtually sold to the pool\n // so the virtual inventory should be increased\n // if the open interest for shorts is decreased then tokens were virtually bought from the pool\n // so the virtual inventory should be decreased\n applyDeltaToVirtualInventoryForPositions(\n dataStore,\n eventEmitter,\n market.indexToken,\n isLong ? -delta : delta\n );\n\n if (delta > 0) {\n validateOpenInterest(\n dataStore,\n market,\n isLong\n );\n }\n\n MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);\n\n return nextValue;\n }\n\n // @dev apply a delta to the open interest in tokens\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param collateralToken the collateralToken to apply to\n // @param isLong whether to apply to the long or short side\n // @param delta the delta amount\n function applyDeltaToOpenInterestInTokens(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n int256 delta\n ) internal returns (uint256) {\n uint256 nextValue = dataStore.applyDeltaToUint(\n Keys.openInterestInTokensKey(market, collateralToken, isLong),\n delta,\n \"Invalid state: negative open interest in tokens\"\n );\n\n MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\n\n return nextValue;\n }\n\n // @dev apply a delta to the collateral sum\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param collateralToken the collateralToken to apply to\n // @param isLong whether to apply to the long or short side\n // @param delta the delta amount\n function applyDeltaToCollateralSum(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n int256 delta\n ) internal returns (uint256) {\n uint256 nextValue = dataStore.applyDeltaToUint(\n Keys.collateralSumKey(market, collateralToken, isLong),\n delta,\n \"Invalid state: negative collateralSum\"\n );\n\n MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);\n\n return nextValue;\n }\n\n // @dev update the funding state\n // @param dataStore DataStore\n // @param market the market to update\n // @param prices the prices of the market tokens\n function updateFundingState(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Market.Props memory market,\n MarketPrices memory prices\n ) external {\n GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);\n\n applyDeltaToFundingFeeAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.longToken,\n true,\n result.fundingFeeAmountPerSizeDelta.long.longToken\n );\n\n applyDeltaToFundingFeeAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.longToken,\n false,\n result.fundingFeeAmountPerSizeDelta.short.longToken\n );\n\n applyDeltaToFundingFeeAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.shortToken,\n true,\n result.fundingFeeAmountPerSizeDelta.long.shortToken\n );\n\n applyDeltaToFundingFeeAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.shortToken,\n false,\n result.fundingFeeAmountPerSizeDelta.short.shortToken\n );\n\n applyDeltaToClaimableFundingAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.longToken,\n true,\n result.claimableFundingAmountPerSizeDelta.long.longToken\n );\n\n applyDeltaToClaimableFundingAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.longToken,\n false,\n result.claimableFundingAmountPerSizeDelta.short.longToken\n );\n\n applyDeltaToClaimableFundingAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.shortToken,\n true,\n result.claimableFundingAmountPerSizeDelta.long.shortToken\n );\n\n applyDeltaToClaimableFundingAmountPerSize(\n dataStore,\n eventEmitter,\n market.marketToken,\n market.shortToken,\n false,\n result.claimableFundingAmountPerSizeDelta.short.shortToken\n );\n\n setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);\n\n dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());\n\n MarketEventUtils.emitFunding(\n eventEmitter,\n market.marketToken,\n result.fundingFactorPerSecond\n );\n }\n\n // @dev get the next funding amount per size values\n // @param dataStore DataStore\n // @param prices the prices of the market tokens\n // @param market the market to update\n // @param longToken the market's long token\n // @param shortToken the market's short token\n function getNextFundingAmountPerSize(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices\n ) internal view returns (GetNextFundingAmountPerSizeResult memory) {\n GetNextFundingAmountPerSizeResult memory result;\n GetNextFundingAmountPerSizeCache memory cache;\n\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\n\n // get the open interest values by long / short and by collateral used\n cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);\n cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);\n cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);\n cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);\n\n // sum the open interest values to get the total long and short open interest values\n cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;\n cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;\n\n // if either long or short open interest is zero, then funding should not be updated\n // as there would not be any user to pay the funding to\n if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {\n return result;\n }\n\n // if the blockchain is not progressing / a market is disabled, funding fees\n // will continue to accumulate\n // this should be a rare occurrence so funding fees are not adjusted for this case\n cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);\n\n (result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(\n dataStore,\n market.marketToken,\n cache.longOpenInterest,\n cache.shortOpenInterest,\n cache.durationInSeconds\n );\n\n cache.sizeOfPayingSide = result.longsPayShorts ? cache.longOpenInterest : cache.shortOpenInterest;\n\n // for single token markets, if there is $200,000 long open interest\n // and $100,000 short open interest and if the fundingUsd is $8:\n // fundingUsdForLongCollateral: $4\n // fundingUsdForShortCollateral: $4\n // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000\n // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000\n // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000\n // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000\n //\n // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the\n // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2\n //\n // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\n //\n // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged\n //\n // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:\n // 4 / 100,000 + 4 / 100,000 = 8 / 100,000\n //\n // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize\n // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken\n //\n // since both these values will be duplicated, the amount claimable would be:\n // (8 / 100,000 + 8 / 100,000) * 100,000 = $16\n //\n // due to these, the fundingUsd should be divided by the divisor\n\n cache.fundingUsd = Precision.applyFactor(cache.sizeOfPayingSide, cache.durationInSeconds * result.fundingFactorPerSecond);\n cache.fundingUsd = cache.fundingUsd / divisor;\n\n // split the fundingUsd value by long and short collateral\n // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest\n // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees\n // should be paid from long positions using short collateral\n // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral\n if (result.longsPayShorts) {\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);\n } else {\n cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);\n cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);\n }\n\n // calculate the change in funding amount per size values\n // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000\n // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1\n // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1\n if (result.longsPayShorts) {\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\n // positions only pay funding in the position's collateral token\n // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral\n // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral\n result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForLongCollateral,\n cache.openInterest.long.longToken,\n prices.longTokenPrice.max,\n true // roundUpMagnitude\n );\n\n result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForShortCollateral,\n cache.openInterest.long.shortToken,\n prices.shortTokenPrice.max,\n true // roundUpMagnitude\n );\n\n // positions receive funding in both the longToken and shortToken\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest\n result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForLongCollateral,\n cache.shortOpenInterest,\n prices.longTokenPrice.max,\n false // roundUpMagnitude\n );\n\n result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForShortCollateral,\n cache.shortOpenInterest,\n prices.shortTokenPrice.max,\n false // roundUpMagnitude\n );\n } else {\n // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received\n // positions only pay funding in the position's collateral token\n // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral\n // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral\n result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForLongCollateral,\n cache.openInterest.short.longToken,\n prices.longTokenPrice.max,\n true // roundUpMagnitude\n );\n\n result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForShortCollateral,\n cache.openInterest.short.shortToken,\n prices.shortTokenPrice.max,\n true // roundUpMagnitude\n );\n\n // positions receive funding in both the longToken and shortToken\n // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest\n result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForLongCollateral,\n cache.longOpenInterest,\n prices.longTokenPrice.max,\n false // roundUpMagnitude\n );\n\n result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(\n cache.fundingUsdForShortCollateral,\n cache.longOpenInterest,\n prices.shortTokenPrice.max,\n false // roundUpMagnitude\n );\n }\n\n return result;\n }\n\n // @dev get the next funding factor per second\n // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped\n // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents\n // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip\n // if it is bound by minFundingFactorPerSecond\n // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond\n // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond\n // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond\n function getNextFundingFactorPerSecond(\n DataStore dataStore,\n address market,\n uint256 longOpenInterest,\n uint256 shortOpenInterest,\n uint256 durationInSeconds\n ) internal view returns (uint256, bool, int256) {\n GetNextFundingFactorPerSecondCache memory cache;\n\n cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);\n cache.totalOpenInterest = longOpenInterest + shortOpenInterest;\n\n FundingConfigCache memory configCache;\n configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));\n\n // if the open interest difference is zero and adaptive funding\n // is not enabled, then return zero as the funding factor\n if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {\n return (0, true, 0);\n }\n\n if (cache.totalOpenInterest == 0) {\n revert Errors.UnableToGetFundingFactorEmptyOpenInterest();\n }\n\n cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);\n\n cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);\n cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);\n\n if (configCache.fundingIncreaseFactorPerSecond == 0) {\n cache.fundingFactor = getFundingFactor(dataStore, market);\n uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\n\n // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference\n uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);\n\n if (fundingFactorPerSecond > maxFundingFactorPerSecond) {\n fundingFactorPerSecond = maxFundingFactorPerSecond;\n }\n\n return (\n fundingFactorPerSecond,\n longOpenInterest > shortOpenInterest,\n 0\n );\n }\n\n // if the savedFundingFactorPerSecond is positive then longs pay shorts\n // if the savedFundingFactorPerSecond is negative then shorts pay longs\n cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);\n cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();\n\n configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));\n configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));\n\n // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;\n\n // the default will be NoChange\n FundingRateChangeType fundingRateChangeType;\n\n bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);\n\n if (isSkewTheSameDirectionAsFunding) {\n if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {\n fundingRateChangeType = FundingRateChangeType.Increase;\n } else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {\n // if thresholdForDecreaseFunding is zero and diffUsdToOpenInterestFactor is also zero\n // then the fundingRateChangeType would be NoChange\n fundingRateChangeType = FundingRateChangeType.Decrease;\n }\n } else {\n // if the skew has changed, then the funding should increase in the opposite direction\n fundingRateChangeType = FundingRateChangeType.Increase;\n }\n\n if (fundingRateChangeType == FundingRateChangeType.Increase) {\n // increase funding rate\n int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();\n\n // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase\n // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease\n if (longOpenInterest < shortOpenInterest) {\n increaseValue = -increaseValue;\n }\n\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;\n }\n\n if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {\n configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));\n uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;\n\n if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {\n // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond\n cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\n } else {\n // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond\n int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();\n cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;\n }\n }\n\n configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));\n configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));\n\n cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(\n cache.nextSavedFundingFactorPerSecond,\n 0,\n configCache.maxFundingFactorPerSecond\n );\n\n cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(\n cache.nextSavedFundingFactorPerSecond,\n configCache.minFundingFactorPerSecond,\n configCache.maxFundingFactorPerSecond\n );\n\n return (\n cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),\n cache.nextSavedFundingFactorPerSecondWithMinBound > 0,\n cache.nextSavedFundingFactorPerSecond\n );\n }\n\n // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size\n function getFundingAmountPerSizeDelta(\n uint256 fundingUsd,\n uint256 openInterest,\n uint256 tokenPrice,\n bool roundUpMagnitude\n ) internal pure returns (uint256) {\n if (fundingUsd == 0 || openInterest == 0) { return 0; }\n\n uint256 fundingUsdPerSize = Precision.mulDiv(\n fundingUsd,\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\n openInterest,\n roundUpMagnitude\n );\n\n if (roundUpMagnitude) {\n return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);\n } else {\n return fundingUsdPerSize / tokenPrice;\n }\n }\n\n // @dev update the cumulative borrowing factor for a market\n // @param dataStore DataStore\n // @param market the market to update\n // @param longToken the market's long token\n // @param shortToken the market's short token\n // @param prices the prices of the market tokens\n // @param isLong whether to update the long or short side\n function updateCumulativeBorrowingFactor(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) external {\n (/* uint256 nextCumulativeBorrowingFactor */, uint256 delta, uint256 borrowingFactorPerSecond) = getNextCumulativeBorrowingFactor(\n dataStore,\n market,\n prices,\n isLong\n );\n\n incrementCumulativeBorrowingFactor(\n dataStore,\n eventEmitter,\n market.marketToken,\n isLong,\n delta\n );\n\n dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());\n\n MarketEventUtils.emitBorrowing(\n eventEmitter,\n market.marketToken,\n borrowingFactorPerSecond\n );\n }\n\n // @dev get the ratio of pnl to pool value\n // @param dataStore DataStore\n // @param oracle Oracle\n // @param market the trading market\n // @param isLong whether to get the value for the long or short side\n // @param maximize whether to maximize the factor\n // @return (pnl of positions) / (long or short pool value)\n function getPnlToPoolFactor(\n DataStore dataStore,\n IOracle oracle,\n address market,\n bool isLong,\n bool maximize\n ) internal view returns (int256) {\n Market.Props memory _market = getEnabledMarket(dataStore, market);\n MarketPrices memory prices = MarketPrices(\n oracle.getPrimaryPrice(_market.indexToken),\n oracle.getPrimaryPrice(_market.longToken),\n oracle.getPrimaryPrice(_market.shortToken)\n );\n\n return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);\n }\n\n // @dev get the ratio of pnl to pool value\n // @param dataStore DataStore\n // @param market the market values\n // @param prices the prices of the market tokens\n // @param isLong whether to get the value for the long or short side\n // @param maximize whether to maximize the factor\n // @return (pnl of positions) / (long or short pool value)\n function getPnlToPoolFactor(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong,\n bool maximize\n ) internal view returns (int256) {\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);\n\n if (poolUsd == 0) {\n return 0;\n }\n\n // note that this PnL does not factor in the PnL from\n // the pending price impact of positions\n int256 pnl = getPnl(\n dataStore,\n market,\n prices.indexTokenPrice,\n isLong,\n maximize\n );\n\n return Precision.toFactor(pnl, poolUsd);\n }\n\n function validateOpenInterest(\n DataStore dataStore,\n Market.Props memory market,\n bool isLong\n ) internal view {\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\n uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);\n\n if (openInterest > maxOpenInterest) {\n revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);\n }\n }\n\n // @dev validate that the pool amount is within the max allowed amount\n // @param dataStore DataStore\n // @param market the market to check\n // @param token the token to check\n function validatePoolAmount(\n DataStore dataStore,\n Market.Props memory market,\n address token\n ) internal view {\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\n uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);\n\n if (poolAmount > maxPoolAmount) {\n revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);\n }\n }\n\n function validatePoolUsdForDeposit(\n DataStore dataStore,\n Market.Props memory market,\n address token,\n uint256 tokenPrice\n ) internal view {\n uint256 poolAmount = getPoolAmount(dataStore, market, token);\n uint256 poolUsd = poolAmount * tokenPrice;\n uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);\n\n if (poolUsd > maxPoolUsd) {\n revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);\n }\n }\n\n // @dev validate that the amount of tokens required to be reserved\n // is below the configured threshold\n // @param dataStore DataStore\n // @param market the market values\n // @param prices the prices of the market tokens\n // @param isLong whether to check the long or short side\n function validateReserve(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) internal view {\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\n // additionally, the shortToken may not be a stablecoin\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\n uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\n\n uint256 reservedUsd = getReservedUsd(\n dataStore,\n market,\n prices,\n isLong\n );\n\n if (reservedUsd > maxReservedUsd) {\n revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);\n }\n }\n\n // @dev validate that the amount of tokens required to be reserved for open interest\n // is below the configured threshold\n // @param dataStore DataStore\n // @param market the market values\n // @param prices the prices of the market tokens\n // @param isLong whether to check the long or short side\n function validateOpenInterestReserve(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) internal view {\n // poolUsd is used instead of pool amount as the indexToken may not match the longToken\n // additionally, the shortToken may not be a stablecoin\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\n uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);\n uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);\n\n uint256 reservedUsd = getReservedUsd(\n dataStore,\n market,\n prices,\n isLong\n );\n\n if (reservedUsd > maxReservedUsd) {\n revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);\n }\n }\n\n // @dev update the swap impact pool amount, if it is a positive impact amount\n // cap the impact amount to the amount available in the swap impact pool\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to apply to\n // @param token the token to apply to\n // @param tokenPrice the price of the token\n // @param priceImpactUsd the USD price impact\n function applySwapImpactWithCap(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n Price.Props memory tokenPrice,\n int256 priceImpactUsd\n ) internal returns (int256, uint256) {\n (int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(\n dataStore,\n market,\n token,\n tokenPrice,\n priceImpactUsd\n );\n\n // if there is a positive impact, the impact pool amount should be reduced\n // if there is a negative impact, the impact pool amount should be increased\n applyDeltaToSwapImpactPool(\n dataStore,\n eventEmitter,\n market,\n token,\n -impactAmount\n );\n\n return (impactAmount, cappedDiffUsd);\n }\n\n function getSwapImpactAmountWithCap(\n DataStore dataStore,\n address market,\n address token,\n Price.Props memory tokenPrice,\n int256 priceImpactUsd\n ) internal view returns (int256, uint256) {\n int256 impactAmount;\n uint256 cappedDiffUsd;\n\n if (priceImpactUsd > 0) {\n // positive impact: minimize impactAmount, use tokenPrice.max\n // round positive impactAmount down, this will be deducted from the swap impact pool for the user\n impactAmount = priceImpactUsd / tokenPrice.max.toInt256();\n\n int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();\n if (impactAmount > maxImpactAmount) {\n cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;\n impactAmount = maxImpactAmount;\n }\n } else {\n // negative impact: maximize impactAmount, use tokenPrice.min\n // round negative impactAmount up, this will be deducted from the user\n impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);\n }\n\n return (impactAmount, cappedDiffUsd);\n }\n\n // @dev get the funding amount to be deducted or distributed\n //\n // @param latestFundingAmountPerSize the latest funding amount per size\n // @param positionFundingAmountPerSize the funding amount per size for the position\n // @param positionSizeInUsd the position size in USD\n // @param roundUpMagnitude whether the round up the result\n //\n // @return fundingAmount\n function getFundingAmount(\n uint256 latestFundingAmountPerSize,\n uint256 positionFundingAmountPerSize,\n uint256 positionSizeInUsd,\n bool roundUpMagnitude\n ) internal pure returns (uint256) {\n uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);\n\n // a user could avoid paying funding fees by continually updating the position\n // before the funding fee becomes large enough to be chargeable\n // to avoid this, funding fee amounts should be rounded up\n //\n // this could lead to large additional charges if the token has a low number of decimals\n // or if the token's value is very high, so care should be taken to inform users of this\n //\n // if the calculation is for the claimable amount, the amount should be rounded down instead\n\n // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values\n // are stored based on FLOAT_PRECISION_SQRT values\n return Precision.mulDiv(\n positionSizeInUsd,\n fundingDiffFactor,\n Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,\n roundUpMagnitude\n );\n }\n\n // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor\n // has already been updated to the latest value\n // @param dataStore DataStore\n // @param position Position.Props\n // @return the borrowing fees for a position\n function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());\n if (position.borrowingFactor() > cumulativeBorrowingFactor) {\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);\n }\n uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\n }\n\n // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor\n // @param dataStore DataStore\n // @param position Position.Props\n // @param market the position's market\n // @param prices the prices of the market tokens\n // @return the borrowing fees for a position\n function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\n dataStore,\n market,\n prices,\n position.isLong()\n );\n\n if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {\n revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);\n }\n uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();\n return Precision.applyFactor(position.sizeInUsd(), diffFactor);\n }\n\n // @dev get the total reserved USD required for positions\n // @param market the market to check\n // @param prices the prices of the market tokens\n // @param isLong whether to get the value for the long or short side\n function getReservedUsd(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) internal view returns (uint256) {\n uint256 reservedUsd;\n if (isLong) {\n // for longs calculate the reserved USD based on the open interest and current indexTokenPrice\n // this works well for e.g. an ETH / USD market with long collateral token as WETH\n // the available amount to be reserved would scale with the price of ETH\n // this also works for e.g. a SOL / USD market with long collateral token as WETH\n // if the price of SOL increases more than the price of ETH, additional amounts would be\n // automatically reserved\n uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);\n reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;\n } else {\n // for shorts use the open interest as the reserved USD value\n // this works well for e.g. an ETH / USD market with short collateral token as USDC\n // the available amount to be reserved would not change with the price of ETH\n reservedUsd = getOpenInterest(dataStore, market, isLong);\n }\n\n return reservedUsd;\n }\n\n // @dev get the virtual inventory for swaps\n // @param dataStore DataStore\n // @param market the market to check\n // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)\n function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));\n if (virtualMarketId == bytes32(0)) {\n return (false, 0, 0);\n }\n\n return (\n true,\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),\n dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))\n );\n }\n\n function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {\n if (token != market.longToken && token != market.shortToken) {\n revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);\n }\n\n return token == market.longToken;\n }\n\n // @dev get the virtual inventory for positions\n // @param dataStore DataStore\n // @param token the token to check\n function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\n if (virtualTokenId == bytes32(0)) {\n return (false, 0);\n }\n\n return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));\n }\n\n // @dev update the virtual inventory for swaps\n // @param dataStore DataStore\n // @param marketAddress the market to update\n // @param token the token to update\n // @param delta the update amount\n function applyDeltaToVirtualInventoryForSwaps(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Market.Props memory market,\n address token,\n int256 delta\n ) internal returns (bool, uint256) {\n bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));\n if (virtualMarketId == bytes32(0)) {\n return (false, 0);\n }\n\n bool isLongToken = getIsLongToken(market, token);\n\n uint256 nextValue = dataStore.applyBoundedDeltaToUint(\n Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),\n delta\n );\n\n MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);\n\n return (true, nextValue);\n }\n\n // @dev update the virtual inventory for positions\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param token the token to update\n // @param delta the update amount\n function applyDeltaToVirtualInventoryForPositions(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address token,\n int256 delta\n ) internal returns (bool, int256) {\n bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));\n if (virtualTokenId == bytes32(0)) {\n return (false, 0);\n }\n\n int256 nextValue = dataStore.applyDeltaToInt(\n Keys.virtualInventoryForPositionsKey(virtualTokenId),\n delta\n );\n\n MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);\n\n return (true, nextValue);\n }\n\n // @dev get the open interest of a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n function getOpenInterest(\n DataStore dataStore,\n Market.Props memory market\n ) internal view returns (uint256) {\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\n\n return longOpenInterest + shortOpenInterest;\n }\n\n // @dev get either the long or short open interest for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param isLong whether to get the long or short open interest\n // @return the long or short open interest for a market\n function getOpenInterest(\n DataStore dataStore,\n Market.Props memory market,\n bool isLong\n ) internal view returns (uint256) {\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);\n\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\n }\n\n // @dev the long and short open interest for a market based on the collateral token used\n // @param dataStore DataStore\n // @param market the market to check\n // @param collateralToken the collateral token to check\n // @param isLong whether to check the long or short side\n function getOpenInterest(\n DataStore dataStore,\n address market,\n address collateralToken,\n bool isLong,\n uint256 divisor\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;\n }\n\n // this is used to divide the values of getPoolAmount and getOpenInterest\n // if the longToken and shortToken are the same, then these values have to be divided by two\n // to avoid double counting\n function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {\n return longToken == shortToken ? 2 : 1;\n }\n\n // @dev the long and short open interest in tokens for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param isLong whether to check the long or short side\n function getOpenInterestInTokens(\n DataStore dataStore,\n Market.Props memory market,\n bool isLong\n ) internal view returns (uint256) {\n uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);\n uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);\n uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);\n\n return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;\n }\n\n // @dev the long and short open interest in tokens for a market based on the collateral token used\n // @param dataStore DataStore\n // @param market the market to check\n // @param collateralToken the collateral token to check\n // @param isLong whether to check the long or short side\n function getOpenInterestInTokens(\n DataStore dataStore,\n address market,\n address collateralToken,\n bool isLong,\n uint256 divisor\n ) internal view returns (uint256) {\n return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;\n }\n\n // @dev get the sum of open interest and pnl for a market\n // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl\n // for short positions, so getOpenInterestWithPnl should be used if that info is needed\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param indexTokenPrice the price of the index token\n // @param isLong whether to check the long or short side\n // @param maximize whether to maximize or minimize the value\n // @return the sum of open interest and pnl for a market\n function getOpenInterestWithPnl(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n bool isLong,\n bool maximize\n ) internal view returns (int256) {\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\n int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\n return Calc.sumReturnInt256(openInterest, pnl);\n }\n\n // @dev get the max position impact factor for decreasing position\n // @param dataStore DataStore\n // @param market the market to check\n // @param isPositive whether the price impact is positive or negative\n function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {\n (uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);\n\n return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;\n }\n\n function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {\n uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));\n uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));\n\n if (maxPositiveImpactFactor > maxNegativeImpactFactor) {\n maxPositiveImpactFactor = maxNegativeImpactFactor;\n }\n\n return (maxPositiveImpactFactor, maxNegativeImpactFactor);\n }\n\n // @dev get the max position impact factor for liquidations\n // @param dataStore DataStore\n // @param market the market to check\n function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {\n return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));\n }\n\n // @dev get the min collateral factor\n // @param dataStore DataStore\n // @param market the market to check\n // @notice Should always be larger than minCollateralFactorForLiquidation\n // to ensure users cannot create immediately liquidatable positions.\n function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {\n return dataStore.getUint(Keys.minCollateralFactorKey(market));\n }\n\n // @dev get the min collateral factor for liquidation\n // @param dataStore DataStore\n // @param market the market to check\n // @notice Should be lower than minCollateralFactor to prevent immediately liquidatable positions.\n function getMinCollateralFactorForLiquidation(DataStore dataStore, address market) internal view returns (uint256) {\n return dataStore.getUint(Keys.minCollateralFactorForLiquidationKey(market));\n }\n\n // @dev get the min collateral factor for open interest multiplier\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether it is for the long or short side\n function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));\n }\n\n // @dev get the min collateral factor for open interest\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param openInterestDelta the change in open interest\n // @param isLong whether it is for the long or short side\n function getMinCollateralFactorForOpenInterest(\n DataStore dataStore,\n Market.Props memory market,\n int256 openInterestDelta,\n bool isLong\n ) internal view returns (uint256) {\n uint256 openInterest = getOpenInterest(dataStore, market, isLong);\n openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);\n uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);\n return Precision.applyFactor(openInterest, multiplierFactor);\n }\n\n // @dev get the total amount of position collateral for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param collateralToken the collateralToken to check\n // @param isLong whether to get the value for longs or shorts\n // @return the total amount of position collateral for a market\n function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {\n return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;\n }\n\n // @dev get the reserve factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to get the value for longs or shorts\n // @return the reserve factor for a market\n function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.reserveFactorKey(market, isLong));\n }\n\n // @dev get the open interest reserve factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to get the value for longs or shorts\n // @return the open interest reserve factor for a market\n function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));\n }\n\n // @dev get the max pnl factor for a market\n // @param dataStore DataStore\n // @param pnlFactorType the type of the pnl factor\n // @param market the market to check\n // @param isLong whether to get the value for longs or shorts\n // @return the max pnl factor for a market\n function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));\n }\n\n // @dev get the min pnl factor after ADL\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));\n }\n\n // @dev get the funding factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @return the funding factor for a market\n function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {\n return dataStore.getUint(Keys.fundingFactorKey(market));\n }\n\n // @dev get the saved funding factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @return the saved funding factor for a market\n function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {\n return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));\n }\n\n // @dev set the saved funding factor\n // @param dataStore DataStore\n // @param market the market to set the funding factor for\n function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {\n return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);\n }\n\n // @dev get the funding exponent factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @return the funding exponent factor for a market\n function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {\n return dataStore.getUint(Keys.fundingExponentFactorKey(market));\n }\n\n // @dev get the funding fee amount per size for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param collateralToken the collateralToken to check\n // @param isLong whether to check the long or short size\n // @return the funding fee amount per size for a market based on collateralToken\n function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));\n }\n\n // @dev get the claimable funding amount per size for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param collateralToken the collateralToken to check\n // @param isLong whether to check the long or short size\n // @return the claimable funding amount per size for a market based on collateralToken\n function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));\n }\n\n // @dev apply delta to the funding fee amount per size for a market\n // @param dataStore DataStore\n // @param market the market to set\n // @param collateralToken the collateralToken to set\n // @param isLong whether to set it for the long or short side\n // @param delta the delta to increment by\n function applyDeltaToFundingFeeAmountPerSize(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n uint256 delta\n ) internal {\n if (delta == 0) { return; }\n\n uint256 nextValue = dataStore.applyDeltaToUint(\n Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),\n delta\n );\n\n MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(\n eventEmitter,\n market,\n collateralToken,\n isLong,\n delta,\n nextValue\n );\n }\n\n // @dev apply delta to the claimable funding amount per size for a market\n // @param dataStore DataStore\n // @param market the market to set\n // @param collateralToken the collateralToken to set\n // @param isLong whether to set it for the long or short side\n // @param delta the delta to increment by\n function applyDeltaToClaimableFundingAmountPerSize(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address collateralToken,\n bool isLong,\n uint256 delta\n ) internal {\n if (delta == 0) { return; }\n\n uint256 nextValue = dataStore.applyDeltaToUint(\n Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),\n delta\n );\n\n MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(\n eventEmitter,\n market,\n collateralToken,\n isLong,\n delta,\n nextValue\n );\n }\n\n // @dev get the number of seconds since funding was updated for a market\n // @param market the market to check\n // @return the number of seconds since funding was updated for a market\n function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {\n uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));\n if (updatedAt == 0) { return 0; }\n return Chain.currentTimestamp() - updatedAt;\n }\n\n // @dev get the borrowing factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @return the borrowing factor for a market\n function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));\n }\n\n function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));\n }\n\n // @dev get the borrowing exponent factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @return the borrowing exponent factor for a market\n function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));\n }\n\n // @dev get the cumulative borrowing factor for a market\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @return the cumulative borrowing factor for a market\n function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));\n }\n\n // @dev increase the cumulative borrowing factor\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the market to increment the borrowing factor for\n // @param isLong whether to increment the long or short side\n // @param delta the increase amount\n function incrementCumulativeBorrowingFactor(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n bool isLong,\n uint256 delta\n ) internal {\n uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(\n Keys.cumulativeBorrowingFactorKey(market, isLong),\n delta\n );\n\n MarketEventUtils.emitBorrowingFactorUpdated(\n eventEmitter,\n market,\n isLong,\n delta,\n nextCumulativeBorrowingFactor\n );\n }\n\n // @dev get the timestamp of when the cumulative borrowing factor was last updated\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @return the timestamp of when the cumulative borrowing factor was last updated\n function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));\n }\n\n // @dev get the number of seconds since the cumulative borrowing factor was last updated\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @return the number of seconds since the cumulative borrowing factor was last updated\n function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);\n if (updatedAt == 0) { return 0; }\n return Chain.currentTimestamp() - updatedAt;\n }\n\n // @dev update the total borrowing amount after a position changes size\n // this is the sum of all position.borrowingFactor * position.sizeInUsd\n // @param dataStore DataStore\n // @param market the market to update\n // @param isLong whether to update the long or short side\n // @param prevPositionSizeInUsd the previous position size in USD\n // @param prevPositionBorrowingFactor the previous position borrowing factor\n // @param nextPositionSizeInUsd the next position size in USD\n // @param nextPositionBorrowingFactor the next position borrowing factor\n function updateTotalBorrowing(\n DataStore dataStore,\n address market,\n bool isLong,\n uint256 prevPositionSizeInUsd,\n uint256 prevPositionBorrowingFactor,\n uint256 nextPositionSizeInUsd,\n uint256 nextPositionBorrowingFactor\n ) external {\n uint256 totalBorrowing = getNextTotalBorrowing(\n dataStore,\n market,\n isLong,\n prevPositionSizeInUsd,\n prevPositionBorrowingFactor,\n nextPositionSizeInUsd,\n nextPositionBorrowingFactor\n );\n\n setTotalBorrowing(dataStore, market, isLong, totalBorrowing);\n }\n\n // @dev get the next total borrowing amount after a position changes size\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @param prevPositionSizeInUsd the previous position size in USD\n // @param prevPositionBorrowingFactor the previous position borrowing factor\n // @param nextPositionSizeInUsd the next position size in USD\n // @param nextPositionBorrowingFactor the next position borrowing factor\n function getNextTotalBorrowing(\n DataStore dataStore,\n address market,\n bool isLong,\n uint256 prevPositionSizeInUsd,\n uint256 prevPositionBorrowingFactor,\n uint256 nextPositionSizeInUsd,\n uint256 nextPositionBorrowingFactor\n ) internal view returns (uint256) {\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);\n totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);\n totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);\n\n return totalBorrowing;\n }\n\n // @dev get the next cumulative borrowing factor\n // @param dataStore DataStore\n // @param prices the prices of the market tokens\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param isLong whether to check the long or short side\n function getNextCumulativeBorrowingFactor(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) internal view returns (uint256, uint256, uint256) {\n uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);\n uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(\n dataStore,\n market,\n prices,\n isLong\n );\n\n uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);\n\n uint256 delta = durationInSeconds * borrowingFactorPerSecond;\n uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;\n return (nextCumulativeBorrowingFactor, delta, borrowingFactorPerSecond);\n }\n\n // @dev get the borrowing factor per second\n // @param dataStore DataStore\n // @param market the market to get the borrowing factor per second for\n // @param prices the prices of the market tokens\n // @param isLong whether to get the factor for the long or short side\n function getBorrowingFactorPerSecond(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) internal view returns (uint256) {\n uint256 reservedUsd = getReservedUsd(\n dataStore,\n market,\n prices,\n isLong\n );\n\n if (reservedUsd == 0) { return 0; }\n\n // check if the borrowing fee for the smaller side should be skipped\n // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest\n // then the borrowing fee would be charged for both sides, this should be very rare\n bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);\n if (skipBorrowingFeeForSmallerSide) {\n uint256 longOpenInterest = getOpenInterest(dataStore, market, true);\n uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);\n\n // if getting the borrowing factor for longs and if the longOpenInterest\n // is smaller than the shortOpenInterest, then return zero\n if (isLong && longOpenInterest < shortOpenInterest) {\n return 0;\n }\n\n // if getting the borrowing factor for shorts and if the shortOpenInterest\n // is smaller than the longOpenInterest, then return zero\n if (!isLong && shortOpenInterest < longOpenInterest) {\n return 0;\n }\n }\n\n uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);\n\n if (poolUsd == 0) {\n revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();\n }\n\n uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);\n\n if (optimalUsageFactor != 0) {\n return getKinkBorrowingFactor(\n dataStore,\n market,\n isLong,\n reservedUsd,\n poolUsd,\n optimalUsageFactor\n );\n }\n\n uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);\n uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);\n\n uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);\n uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);\n\n return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);\n }\n\n function getKinkBorrowingFactor(\n DataStore dataStore,\n Market.Props memory market,\n bool isLong,\n uint256 reservedUsd,\n uint256 poolUsd,\n uint256 optimalUsageFactor\n ) internal view returns (uint256) {\n uint256 usageFactor = getUsageFactor(\n dataStore,\n market,\n isLong,\n reservedUsd,\n poolUsd\n );\n\n uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));\n\n uint256 borrowingFactorPerSecond = Precision.applyFactor(\n usageFactor,\n baseBorrowingFactor\n );\n\n if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {\n uint256 diff = usageFactor - optimalUsageFactor;\n\n uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));\n uint256 additionalBorrowingFactorPerSecond;\n\n if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {\n additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;\n }\n\n uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;\n\n borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;\n }\n\n return borrowingFactorPerSecond;\n }\n\n function distributePositionImpactPool(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market\n ) external {\n (uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\n\n if (distributionAmount != 0) {\n applyDeltaToPositionImpactPool(\n dataStore,\n eventEmitter,\n market,\n -distributionAmount.toInt256()\n );\n\n MarketEventUtils.emitPositionImpactPoolDistributed(\n eventEmitter,\n market,\n distributionAmount,\n nextPositionImpactPoolAmount\n );\n }\n\n dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());\n }\n\n function getNextPositionImpactPoolAmount(\n DataStore dataStore,\n address market\n ) internal view returns (uint256) {\n (/* uint256 distributionAmount */, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);\n\n return nextPositionImpactPoolAmount;\n }\n\n // @return (distributionAmount, nextPositionImpactPoolAmount)\n function getPendingPositionImpactPoolDistributionAmount(\n DataStore dataStore,\n address market\n ) internal view returns (uint256, uint256) {\n uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);\n if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }\n\n uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));\n if (distributionRate == 0) { return (0, positionImpactPoolAmount); }\n\n uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));\n if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }\n\n uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;\n\n uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);\n uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);\n\n if (distributionAmount > maxDistributionAmount) {\n distributionAmount = maxDistributionAmount;\n }\n\n return (distributionAmount, positionImpactPoolAmount - distributionAmount);\n }\n\n function getSecondsSincePositionImpactPoolDistributed(\n DataStore dataStore,\n address market\n ) internal view returns (uint256) {\n uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));\n if (distributedAt == 0) { return 0; }\n return Chain.currentTimestamp() - distributedAt;\n }\n\n // @dev get the total pending borrowing fees\n // @param dataStore DataStore\n // @param market the market to check\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param isLong whether to check the long or short side\n function getTotalPendingBorrowingFees(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong\n ) internal view returns (uint256) {\n uint256 openInterest = getOpenInterest(\n dataStore,\n market,\n isLong\n );\n\n (uint256 nextCumulativeBorrowingFactor, /* uint256 delta */, ) = getNextCumulativeBorrowingFactor(\n dataStore,\n market,\n prices,\n isLong\n );\n\n uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);\n\n return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;\n }\n\n // @dev get the total borrowing value\n // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)\n // for all positions of the market\n // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 10 * (10 ** 30)\n // (100% is 10 ** 30 so 1000% is 10 * (10 ** 30))\n // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues\n // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 10 * (10 ** 30)) => 115,792,090,000,000 USD\n // @param dataStore DataStore\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @return the total borrowing value\n function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {\n return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));\n }\n\n // @dev set the total borrowing value\n // @param dataStore DataStore\n // @param market the market to set\n // @param isLong whether to set the long or short side\n // @param value the value to set to\n function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {\n return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);\n }\n\n // @dev convert a USD value to number of market tokens\n // @param usdValue the input USD value\n // @param poolValue the value of the pool\n // @param supply the supply of market tokens\n // @return the number of market tokens\n function usdToMarketTokenAmount(\n uint256 usdValue,\n uint256 poolValue,\n uint256 supply\n ) internal pure returns (uint256) {\n // if the supply and poolValue is zero, use 1 USD as the token price\n if (supply == 0 && poolValue == 0) {\n return Precision.floatToWei(usdValue);\n }\n\n // if the supply is zero and the poolValue is more than zero,\n // then include the poolValue for the amount of tokens minted so that\n // the market token price after mint would be 1 USD\n if (supply == 0 && poolValue > 0) {\n return Precision.floatToWei(poolValue + usdValue);\n }\n\n // round market tokens down\n return Precision.mulDiv(supply, usdValue, poolValue);\n }\n\n // @dev convert a number of market tokens to its USD value\n // @param marketTokenAmount the input number of market tokens\n // @param poolValue the value of the pool\n // @param supply the supply of market tokens\n // @return the USD value of the market tokens\n function marketTokenAmountToUsd(\n uint256 marketTokenAmount,\n uint256 poolValue,\n uint256 supply\n ) internal pure returns (uint256) {\n if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }\n\n return Precision.mulDiv(poolValue, marketTokenAmount, supply);\n }\n\n // @dev validate that the specified market exists and is enabled\n // @param dataStore DataStore\n // @param marketAddress the address of the market\n function validateEnabledMarket(DataStore dataStore, address marketAddress) external view {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n validateEnabledMarket(dataStore, market);\n }\n\n // @dev validate that the specified market exists and is enabled\n // @param dataStore DataStore\n // @param market the market to check\n function validateEnabledMarket(DataStore dataStore, Market.Props memory market) public view {\n if (market.marketToken == address(0)) {\n revert Errors.EmptyMarket();\n }\n\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\n if (isMarketDisabled) {\n revert Errors.DisabledMarket(market.marketToken);\n }\n }\n\n // @dev validate that the positions can be opened in the given market\n // @param market the market to check\n function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {\n validateEnabledMarket(dataStore, market);\n\n if (isSwapOnlyMarket(market)) {\n revert Errors.InvalidPositionMarket(market.marketToken);\n }\n }\n\n function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n validatePositionMarket(dataStore, market);\n }\n\n // @dev check if a market only supports swaps and not positions\n // @param market the market to check\n function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {\n return market.indexToken == address(0);\n }\n\n // @dev check if the given token is a collateral token of the market\n // @param market the market to check\n // @param token the token to check\n function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {\n return token == market.longToken || token == market.shortToken;\n }\n\n // @dev validate if the given token is a collateral token of the market\n // @param market the market to check\n // @param token the token to check\n function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {\n if (!isMarketCollateralToken(market, token)) {\n revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);\n }\n }\n\n // @dev get the enabled market, revert if the market does not exist or is not enabled\n // @param dataStore DataStore\n // @param marketAddress the address of the market\n function getEnabledMarket(DataStore dataStore, address marketAddress) public view returns (Market.Props memory) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n validateEnabledMarket(dataStore, market);\n return market;\n }\n\n function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n validateSwapMarket(dataStore, market);\n return market;\n }\n\n // @dev get a list of market values based on an input array of market addresses\n // @param swapPath list of market addresses\n function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) external view returns (Market.Props[] memory) {\n Market.Props[] memory markets = new Market.Props[](swapPath.length);\n\n for (uint256 i; i < swapPath.length; i++) {\n address marketAddress = swapPath[i];\n markets[i] = getSwapPathMarket(dataStore, marketAddress);\n }\n\n return markets;\n }\n\n function validateSwapPath(DataStore dataStore, address[] memory swapPath) external view {\n uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);\n if (swapPath.length > maxSwapPathLength) {\n revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);\n }\n\n for (uint256 i; i < swapPath.length; i++) {\n address marketAddress = swapPath[i];\n validateSwapMarket(dataStore, marketAddress);\n }\n }\n\n // @dev validate that the pending pnl is below the allowed amount\n // @param dataStore DataStore\n // @param market the market to check\n // @param prices the prices of the market tokens\n // @param pnlFactorType the pnl factor type to check\n function validateMaxPnl(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bytes32 pnlFactorTypeForLongs,\n bytes32 pnlFactorTypeForShorts\n ) internal view {\n (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(\n dataStore,\n market,\n prices,\n true,\n pnlFactorTypeForLongs\n );\n\n if (isPnlFactorExceededForLongs) {\n revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);\n }\n\n (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(\n dataStore,\n market,\n prices,\n false,\n pnlFactorTypeForShorts\n );\n\n if (isPnlFactorExceededForShorts) {\n revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);\n }\n }\n\n // @dev check if the pending pnl exceeds the allowed amount\n // @param dataStore DataStore\n // @param oracle Oracle\n // @param market the market to check\n // @param isLong whether to check the long or short side\n // @param pnlFactorType the pnl factor type to check\n function isPnlFactorExceeded(\n DataStore dataStore,\n IOracle oracle,\n address market,\n bool isLong,\n bytes32 pnlFactorType\n ) internal view returns (bool, int256, uint256) {\n Market.Props memory _market = getEnabledMarket(dataStore, market);\n MarketPrices memory prices = getMarketPrices(oracle, _market);\n\n return isPnlFactorExceeded(\n dataStore,\n _market,\n prices,\n isLong,\n pnlFactorType\n );\n }\n\n // @dev check if the pending pnl exceeds the allowed amount\n // @param dataStore DataStore\n // @param _market the market to check\n // @param prices the prices of the market tokens\n // @param isLong whether to check the long or short side\n // @param pnlFactorType the pnl factor type to check\n function isPnlFactorExceeded(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n bool isLong,\n bytes32 pnlFactorType\n ) internal view returns (bool, int256, uint256) {\n int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);\n uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);\n\n bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;\n\n return (isExceeded, pnlToPoolFactor, maxPnlFactor);\n }\n\n function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\n uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));\n\n return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;\n }\n\n function setUiFeeFactor(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n uint256 uiFeeFactor\n ) internal {\n uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);\n\n if (uiFeeFactor > maxUiFeeFactor) {\n revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);\n }\n\n dataStore.setUint(\n Keys.uiFeeFactorKey(account),\n uiFeeFactor\n );\n\n MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);\n }\n\n function validateMarketTokenBalance(\n DataStore dataStore,\n Market.Props[] memory markets\n ) public view {\n for (uint256 i; i < markets.length; i++) {\n validateMarketTokenBalance(dataStore, markets[i]);\n }\n }\n\n function validateMarketTokenBalance(\n DataStore dataStore,\n address _market\n ) public view {\n Market.Props memory market = getEnabledMarket(dataStore, _market);\n validateMarketTokenBalance(dataStore, market);\n }\n\n function validateMarketTokenBalance(\n DataStore dataStore,\n Market.Props memory market\n ) public view {\n validateMarketTokenBalance(dataStore, market, market.longToken);\n\n if (market.longToken == market.shortToken) {\n return;\n }\n\n validateMarketTokenBalance(dataStore, market, market.shortToken);\n }\n\n function validateMarketTokenBalance(\n DataStore dataStore,\n Market.Props memory market,\n address token\n ) internal view {\n if (market.marketToken == address(0) || token == address(0)) {\n revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);\n }\n\n uint256 balance = IERC20(token).balanceOf(market.marketToken);\n uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);\n\n if (balance < expectedMinBalance) {\n revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);\n }\n\n // funding fees can be claimed even if the collateral for positions that should pay funding fees\n // hasn't been reduced yet\n // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation\n // and validated separately\n\n // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the\n // longToken and shortToken\n uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);\n collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);\n\n if (balance < collateralAmount) {\n revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);\n }\n\n uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));\n\n // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance\n // but this should be very rare\n if (balance < claimableFundingFeeAmount) {\n revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);\n }\n }\n\n function getExpectedMinTokenBalance(\n DataStore dataStore,\n Market.Props memory market,\n address token\n ) internal view returns (uint256) {\n GetExpectedMinTokenBalanceCache memory cache;\n\n // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2\n // for markets with the same long and short token\n cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));\n cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);\n cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));\n cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));\n cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));\n cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));\n\n // funding fees are excluded from this summation as claimable funding fees\n // are incremented without a corresponding decrease of the collateral of\n // other positions, the collateral of other positions is decreased when\n // those positions are updated\n return\n cache.poolAmount\n + cache.swapImpactPoolAmount\n + cache.claimableCollateralAmount\n + cache.claimableFeeAmount\n + cache.claimableUiFeeAmount\n + cache.affiliateRewardAmount;\n }\n\n function getProportionalAmounts(\n DataStore dataStore,\n Market.Props memory market,\n MarketPrices memory prices,\n uint256 totalUsd\n ) internal view returns(uint256, uint256) {\n uint256 longTokenPoolAmount = getPoolAmount(dataStore, market, market.longToken);\n uint256 shortTokenPoolAmount = getPoolAmount(dataStore, market, market.shortToken);\n\n uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;\n uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;\n\n uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;\n\n uint256 longTokenOutputUsd = Precision.mulDiv(totalUsd, longTokenPoolUsd, totalPoolUsd);\n uint256 shortTokenOutputUsd = Precision.mulDiv(totalUsd, shortTokenPoolUsd, totalPoolUsd);\n\n return (longTokenOutputUsd / prices.longTokenPrice.max, shortTokenOutputUsd / prices.shortTokenPrice.max);\n }\n}\n" + }, + "contracts/market/PositionImpactPoolUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport {DataStore} from \"../data/DataStore.sol\";\nimport {Keys} from \"../data/Keys.sol\";\nimport {Errors} from \"../error/Errors.sol\";\nimport {EventEmitter} from \"../event/EventEmitter.sol\";\nimport {Precision} from \"../utils/Precision.sol\";\nimport {Market} from \"./Market.sol\";\nimport {MarketEventUtils} from \"./MarketEventUtils.sol\";\nimport {MarketPoolValueInfo} from \"./MarketPoolValueInfo.sol\";\nimport {MarketStoreUtils} from \"./MarketStoreUtils.sol\";\nimport {MarketToken} from \"./MarketToken.sol\";\nimport {MarketUtils} from \"./MarketUtils.sol\";\nimport {SafeCast} from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport {SignedMath} from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IOracle } from \"../oracle/IOracle.sol\";\nimport \"../position/PositionUtils.sol\";\n\nlibrary PositionImpactPoolUtils {\n using SignedMath for int256;\n using SafeCast for int256;\n using SafeCast for uint256;\n using SafeERC20 for IERC20;\n\n using Market for Market.Props;\n\n // @dev withdraw funds from the position impact pool while maintaining GM token price\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param market the trading market\n // @param receiver the address to receive the withdrawn funds\n // @param amount the amount to withdraw\n // @param oracle - oracle to fetch the market prices\n function withdrawFromPositionImpactPool(\n DataStore dataStore,\n EventEmitter eventEmitter,\n IOracle oracle,\n address market,\n address receiver,\n uint256 amount\n ) external {\n require(amount > 0, \"Amount must be greater than 0\");\n\n MarketUtils.distributePositionImpactPool(\n dataStore,\n eventEmitter,\n market\n );\n\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\n\n PositionUtils.updateFundingAndBorrowingState(\n dataStore,\n eventEmitter,\n marketProps,\n prices\n );\n\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n dataStore,\n marketProps,\n prices.indexTokenPrice,\n prices.longTokenPrice,\n prices.shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n false\n );\n\n if (poolValueInfo.poolValue <= 0) {\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\n }\n\n uint256 adjustedImpactPoolAmount = poolValueInfo.impactPoolAmount;\n int256 totalPendingImpactAmount = MarketUtils.getTotalPendingImpactAmount(dataStore, market);\n\n // if there is a positive totalPendingImpactAmount, that means that the\n // excess should be covered by the position impact pool, so subtract this\n // from the impactPoolAmount that can be withdrawn\n // lent amount is not considered here, because if there is a lent amount\n // we assume that the position impact would be zero\n if (totalPendingImpactAmount > 0) {\n if (adjustedImpactPoolAmount < totalPendingImpactAmount.toUint256()) {\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\n }\n\n adjustedImpactPoolAmount -= totalPendingImpactAmount.toUint256();\n }\n\n if (adjustedImpactPoolAmount < amount) {\n revert Errors.InsufficientImpactPoolValueForWithdrawal(amount, poolValueInfo.impactPoolAmount, totalPendingImpactAmount);\n }\n\n MarketUtils.applyDeltaToPositionImpactPool(\n dataStore,\n eventEmitter,\n market,\n - amount.toInt256()\n );\n\n // Calculate amount of tokens to withdraw:\n // We want to withdraw long and short tokens from the pool\n // at the current pool token ratio\n (uint256 longTokenWithdrawalAmount, uint256 shortTokenWithdrawalAmount) = MarketUtils.getProportionalAmounts(\n dataStore,\n marketProps,\n prices,\n amount * prices.indexTokenPrice.min\n );\n\n MarketUtils.applyDeltaToPoolAmount(\n dataStore,\n eventEmitter,\n marketProps,\n marketProps.longToken,\n - longTokenWithdrawalAmount.toInt256()\n );\n\n MarketUtils.applyDeltaToPoolAmount(\n dataStore,\n eventEmitter,\n marketProps,\n marketProps.shortToken,\n - shortTokenWithdrawalAmount.toInt256()\n );\n\n MarketToken(payable(market)).transferOut(\n marketProps.longToken,\n receiver,\n longTokenWithdrawalAmount\n );\n\n MarketToken(payable(market)).transferOut(\n marketProps.shortToken,\n receiver,\n shortTokenWithdrawalAmount\n );\n\n MarketUtils.validateMarketTokenBalance(dataStore, market);\n\n MarketEventUtils.emitPositionImpactPoolWithdrawal(\n eventEmitter,\n market,\n receiver,\n amount\n );\n }\n\n function reduceLentAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n IOracle oracle,\n address market,\n address fundingAccount,\n uint256 reductionAmount\n ) external {\n Market.Props memory marketProps = MarketStoreUtils.get(dataStore, market);\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, marketProps);\n\n PositionUtils.updateFundingAndBorrowingState(\n dataStore,\n eventEmitter,\n marketProps,\n prices\n );\n\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market));\n\n if (reductionAmount > lentAmount) {\n revert Errors.ReductionExceedsLentAmount(lentAmount, reductionAmount);\n }\n\n uint256 reductionUsd = reductionAmount * prices.indexTokenPrice.max;\n uint256 longTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.longTokenPrice.min);\n uint256 shortTokenAmount = Calc.roundUpDivision(reductionUsd, 2 * prices.shortTokenPrice.min);\n\n if (longTokenAmount > 0) {\n IERC20(marketProps.longToken).safeTransferFrom(fundingAccount, market, longTokenAmount);\n }\n\n if (shortTokenAmount > 0) {\n IERC20(marketProps.shortToken).safeTransferFrom(fundingAccount, market, shortTokenAmount);\n }\n\n MarketUtils.applyDeltaToPoolAmount(\n dataStore,\n eventEmitter,\n marketProps,\n marketProps.longToken,\n longTokenAmount.toInt256()\n );\n\n MarketUtils.applyDeltaToPoolAmount(\n dataStore,\n eventEmitter,\n marketProps,\n marketProps.shortToken,\n shortTokenAmount.toInt256()\n );\n\n uint256 nextValue = dataStore.decrementUint(Keys.lentPositionImpactPoolAmountKey(market), reductionAmount);\n MarketEventUtils.emitLentPositionImpactPoolAmountUpdated(eventEmitter, market, reductionAmount.toInt256(), nextValue);\n\n MarketUtils.validateMarketTokenBalance(dataStore, market);\n\n MarketEventUtils.emitLentImpactAmountReduction(\n eventEmitter,\n market,\n fundingAccount,\n longTokenAmount,\n shortTokenAmount,\n reductionAmount\n );\n }\n}\n" + }, + "contracts/migration/GlpMigrator.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"./IGlpVault.sol\";\nimport \"./IGlpTimelock.sol\";\nimport \"./IGlpRewardRouter.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"../deposit/DepositVault.sol\";\nimport \"../exchange/DepositHandler.sol\";\nimport \"../external/ExternalHandler.sol\";\n\ncontract GlpMigrator is ReentrancyGuard, RoleModule {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n using SafeERC20 for IERC20;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n DepositVault public immutable depositVault;\n DepositHandler public immutable depositHandler;\n ExternalHandler public immutable externalHandler;\n\n IERC20 public immutable stakedGlp;\n IGlpVault public immutable glpVault;\n IGlpTimelock public immutable glpTimelock;\n IGlpRewardRouter public immutable glpRewardRouter;\n\n uint256 public reducedMintBurnFeeBasisPoints;\n\n struct GlpRedemption {\n address token;\n uint256 glpAmount;\n uint256 minOut;\n\n address receiver;\n address[] externalCallTargets;\n bytes[] externalCallDataList;\n address[] refundTokens;\n address[] refundReceivers;\n }\n\n struct MigrationItem {\n address market;\n\n GlpRedemption long;\n GlpRedemption short;\n\n uint256 minMarketTokens;\n uint256 executionFee;\n }\n\n struct MigrateCache {\n Market.Props market;\n uint256 redeemedLongTokenAmount;\n uint256 redeemedShortTokenAmount;\n bytes32 depositKey;\n }\n\n modifier withReducedRedemptionFees() {\n uint256 taxBasisPoints = glpVault.taxBasisPoints();\n uint256 stableTaxBasisPoints = glpVault.stableTaxBasisPoints();\n uint256 mintBurnFeeBasisPoints = glpVault.mintBurnFeeBasisPoints();\n uint256 swapFeeBasisPoints = glpVault.swapFeeBasisPoints();\n uint256 stableSwapFeeBasisPoints = glpVault.stableSwapFeeBasisPoints();\n uint256 _reducedMintBurnFeeBasisPoints = reducedMintBurnFeeBasisPoints;\n\n bool shouldUpdateFees = _reducedMintBurnFeeBasisPoints < mintBurnFeeBasisPoints;\n\n if (shouldUpdateFees) {\n glpTimelock.setSwapFees(\n address(glpVault),\n taxBasisPoints,\n stableTaxBasisPoints,\n _reducedMintBurnFeeBasisPoints,\n swapFeeBasisPoints,\n stableSwapFeeBasisPoints\n );\n }\n\n _;\n\n if (shouldUpdateFees) {\n glpTimelock.setSwapFees(\n address(glpVault),\n taxBasisPoints,\n stableTaxBasisPoints,\n mintBurnFeeBasisPoints,\n swapFeeBasisPoints,\n stableSwapFeeBasisPoints\n );\n }\n }\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n DepositVault _depositVault,\n DepositHandler _depositHandler,\n ExternalHandler _externalHandler,\n IERC20 _stakedGlp,\n IGlpVault _glpVault,\n IGlpTimelock _glpTimelock,\n IGlpRewardRouter _glpRewardRouter,\n uint256 _reducedMintBurnFeeBasisPoints\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n depositVault = _depositVault;\n depositHandler = _depositHandler;\n externalHandler = _externalHandler;\n\n stakedGlp = _stakedGlp;\n glpVault = _glpVault;\n glpTimelock = _glpTimelock;\n glpRewardRouter = _glpRewardRouter;\n\n reducedMintBurnFeeBasisPoints = _reducedMintBurnFeeBasisPoints;\n }\n\n function setReducedMintBurnFeeBasisPoints(uint256 _reducedMintBurnFeeBasisPoints) external onlyConfigKeeper {\n reducedMintBurnFeeBasisPoints = _reducedMintBurnFeeBasisPoints;\n\n EventUtils.EventLogData memory eventData;\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"reducedMintBurnFeeBasisPoints\", _reducedMintBurnFeeBasisPoints);\n\n eventEmitter.emitEventLog(\n \"SetReducedMintBurnFeeBasisPoints\",\n eventData\n );\n }\n\n function migrate(\n uint256 totalGlpAmount,\n MigrationItem[] memory migrationItems\n ) external payable nonReentrant withReducedRedemptionFees {\n address account = msg.sender;\n stakedGlp.transferFrom(account, address(this), totalGlpAmount);\n\n uint256 totalGlpAmountToRedeem;\n uint256 totalExecutionFee;\n\n for (uint256 i = 0; i < migrationItems.length; i++) {\n MigrationItem memory migrationItem = migrationItems[i];\n totalGlpAmountToRedeem += migrationItem.long.glpAmount;\n totalGlpAmountToRedeem += migrationItem.short.glpAmount;\n\n totalExecutionFee += migrationItem.executionFee;\n }\n\n if (totalGlpAmountToRedeem != totalGlpAmount) {\n revert Errors.InvalidGlpAmount(totalGlpAmountToRedeem, totalGlpAmount);\n }\n\n if (msg.value != totalExecutionFee) {\n revert Errors.InvalidExecutionFeeForMigration(totalExecutionFee, msg.value);\n }\n\n for (uint256 i = 0; i < migrationItems.length; i++) {\n MigrationItem memory migrationItem = migrationItems[i];\n MigrateCache memory cache;\n\n cache.market = MarketUtils.getEnabledMarket(dataStore, migrationItem.market);\n\n cache.redeemedLongTokenAmount = _redeemGlp(migrationItem.long);\n cache.redeemedShortTokenAmount = _redeemGlp(migrationItem.short);\n\n TokenUtils.depositAndSendWrappedNativeToken(\n dataStore,\n address(depositVault),\n migrationItem.executionFee\n );\n\n // a user could set a minMarketTokens to force the deposit to fail\n // or set a market where the deposited amount would exceed the caps and\n // the deposit would fail\n // or use the externalHandler calls to set the receiver of tokens\n // directly to an account they own or control\n // glp should be adjusted such that only redemptions are allowed so\n // any arbitrage / benefit of doing this should be minimal\n // glp mint fees should also help to discourage this\n IDepositUtils.CreateDepositParams memory depositParams = IDepositUtils.CreateDepositParams(\n IDepositUtils.CreateDepositParamsAddresses(\n account, // receiver;\n address(0), // callbackContract;\n address(0), // uiFeeReceiver;\n migrationItem.market, // market;\n cache.market.longToken, // initialLongToken;\n cache.market.shortToken, // initialShortToken;\n new address[](0), // longTokenSwapPath;\n new address[](0) // shortTokenSwapPath;\n ),\n migrationItem.minMarketTokens, // minMarketTokens;\n false, // shouldUnwrapNativeToken;\n migrationItem.executionFee, // executionFee;\n 0, // callbackGasLimit;\n new bytes32[](0) // dataList;\n );\n\n cache.depositKey = depositHandler.createDeposit(\n account,\n 0, // srcChainId is the current block.chainId\n depositParams\n );\n\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"depositKey\", cache.depositKey);\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", cache.market.marketToken);\n eventData.addressItems.setItem(1, \"redeemedLongToken\", migrationItem.long.token);\n eventData.addressItems.setItem(2, \"redeemedShortToken\", migrationItem.short.token);\n\n eventData.uintItems.initItems(4);\n eventData.uintItems.setItem(0, \"glpLongAmount\", migrationItem.long.glpAmount);\n eventData.uintItems.setItem(1, \"glpShortAmount\", migrationItem.short.glpAmount);\n eventData.uintItems.setItem(2, \"redeemedLongTokenAmount\", cache.redeemedLongTokenAmount);\n eventData.uintItems.setItem(3, \"redeemedShortTokenAmount\", cache.redeemedShortTokenAmount);\n\n eventEmitter.emitEventLog1(\n \"GlpMigration\",\n Cast.toBytes32(cache.market.marketToken),\n eventData\n );\n }\n }\n\n function _redeemGlp(\n GlpRedemption memory redemptionInfo\n ) internal returns (uint256) {\n if (redemptionInfo.glpAmount == 0) {\n return 0;\n }\n\n uint256 redeemedTokenAmount = glpRewardRouter.unstakeAndRedeemGlp(\n redemptionInfo.token, // tokenOut\n redemptionInfo.glpAmount, // glpAmount\n redemptionInfo.minOut, // minOut\n redemptionInfo.receiver // receiver\n );\n\n externalHandler.makeExternalCalls(\n redemptionInfo.externalCallTargets,\n redemptionInfo.externalCallDataList,\n redemptionInfo.refundTokens,\n redemptionInfo.refundReceivers\n );\n\n return redeemedTokenAmount;\n }\n}\n" + }, + "contracts/migration/IGlpRewardRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IGlpRewardRouter {\n function unstakeAndRedeemGlp(address _tokenOut, uint256 _glpAmount, uint256 _minOut, address _receiver) external returns (uint256);\n}\n" + }, + "contracts/migration/IGlpTimelock.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IGlpTimelock {\n function setSwapFees(\n address _vault,\n uint256 _taxBasisPoints,\n uint256 _stableTaxBasisPoints,\n uint256 _mintBurnFeeBasisPoints,\n uint256 _swapFeeBasisPoints,\n uint256 _stableSwapFeeBasisPoints\n ) external;\n}\n" + }, + "contracts/migration/IGlpVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IGlpVault {\n function taxBasisPoints() external view returns (uint256);\n function stableTaxBasisPoints() external view returns (uint256);\n function mintBurnFeeBasisPoints() external view returns (uint256);\n function swapFeeBasisPoints() external view returns (uint256);\n function stableSwapFeeBasisPoints() external view returns (uint256);\n}\n" + }, + "contracts/migration/TimestampInitializer.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../chain/Chain.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../role/RoleModule.sol\";\nimport \"../order/OrderStoreUtils.sol\";\nimport \"../position/PositionStoreUtils.sol\";\n\ncontract TimestampInitializer is RoleModule {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n\n function initializeOrderTimestamps(uint256 start, uint256 end) external onlyConfigKeeper {\n bytes32[] memory keys = dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end);\n uint256 currentTimestamp = Chain.currentTimestamp();\n\n for (uint256 i; i < keys.length; i++) {\n bytes32 key = keys[i];\n\n uint256 updatedAtTime = dataStore.getUint(\n keccak256(abi.encode(key, OrderStoreUtils.UPDATED_AT_TIME))\n );\n\n if (updatedAtTime == 0) {\n\n dataStore.setUint(\n keccak256(abi.encode(key, OrderStoreUtils.UPDATED_AT_TIME)),\n currentTimestamp\n );\n\n EventUtils.EventLogData memory eventData;\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"updatedAtTime\", currentTimestamp);\n\n eventEmitter.emitEventLog(\n \"InitializeOrderUpdatedAtTime\",\n eventData\n );\n }\n }\n }\n\n function initializePositionTimestamps(uint256 start, uint256 end) external onlyConfigKeeper {\n bytes32[] memory keys = dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end);\n uint256 currentTimestamp = Chain.currentTimestamp();\n\n for (uint256 i; i < keys.length; i++) {\n bytes32 key = keys[i];\n\n uint256 increasedAtTime = dataStore.getUint(\n keccak256(abi.encode(key, PositionStoreUtils.INCREASED_AT_TIME))\n );\n\n if (increasedAtTime == 0) {\n dataStore.setUint(\n keccak256(abi.encode(key, PositionStoreUtils.INCREASED_AT_TIME)),\n currentTimestamp\n );\n\n EventUtils.EventLogData memory eventData;\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"increasedAtTime\", currentTimestamp);\n\n eventEmitter.emitEventLog(\n \"InitializePositionIncreasedAtTime\",\n eventData\n );\n }\n\n uint256 decreasedAtTime = dataStore.getUint(\n keccak256(abi.encode(key, PositionStoreUtils.DECREASED_AT_TIME))\n );\n\n if (decreasedAtTime == 0) {\n dataStore.setUint(\n keccak256(abi.encode(key, PositionStoreUtils.DECREASED_AT_TIME)),\n currentTimestamp\n );\n\n EventUtils.EventLogData memory eventData;\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"decreasedAtTime\", currentTimestamp);\n\n eventEmitter.emitEventLog(\n \"InitializePositionDecreasedAtTime\",\n eventData\n );\n }\n }\n }\n\n}\n" + }, + "contracts/mock/Governable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/Errors.sol\";\n\n// @title Governable\n// @dev Contract to allow for governance restricted functions\ncontract Governable {\n address public gov;\n address public pendingGov;\n\n event SetGov(address prevGov, address nextGov);\n\n constructor() {\n _setGov(msg.sender);\n }\n\n modifier onlyGov() {\n if (msg.sender != gov) {\n revert Errors.Unauthorized(msg.sender, \"GOV\");\n }\n _;\n }\n\n function transferOwnership(address _newGov) external onlyGov {\n pendingGov = _newGov;\n }\n\n function acceptOwnership() external {\n if (msg.sender != pendingGov) {\n revert Errors.Unauthorized(msg.sender, \"PendingGov\");\n }\n\n _setGov(msg.sender);\n }\n\n // @dev updates the gov value to the input _gov value\n // @param _gov the value to update to\n function _setGov(address _gov) internal {\n address prevGov = gov;\n gov = _gov;\n\n emit SetGov(prevGov, _gov);\n }\n}\n" + }, + "contracts/mock/MockCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../callback/IOrderCallbackReceiver.sol\";\nimport \"../callback/IGasFeeCallbackReceiver.sol\";\nimport \"../callback/IGlvDepositCallbackReceiver.sol\";\nimport \"../callback/IGlvWithdrawalCallbackReceiver.sol\";\n\ncontract MockCallbackReceiver is IOrderCallbackReceiver, IGasFeeCallbackReceiver, IGlvDepositCallbackReceiver, IGlvWithdrawalCallbackReceiver {\n uint public called;\n\n uint public glvDepositExecutionCalled;\n uint public glvDepositCancellationCalled;\n uint public glvWithdrawalExecutionCalled;\n uint public glvWithdrawalCancellationCalled;\n\n function afterOrderExecution(bytes32 /* key */, EventUtils.EventLogData memory /* order */, EventUtils.EventLogData memory /* eventData */) external {\n ++called;\n }\n\n function afterOrderCancellation(bytes32 /* key */, EventUtils.EventLogData memory /* order */, EventUtils.EventLogData memory /* eventData */) external {\n ++called;\n }\n\n function afterOrderFrozen(bytes32 /* key */, EventUtils.EventLogData memory /* order */, EventUtils.EventLogData memory /* eventData */) external {\n ++called;\n }\n\n function refundExecutionFee(bytes32 /* key */, EventUtils.EventLogData memory /* eventData */) external payable {\n ++called;\n }\n\n function afterGlvDepositExecution(bytes32 /* key */, EventUtils.EventLogData memory /* glv deposit */, EventUtils.EventLogData memory /* eventData */) external {\n ++glvDepositExecutionCalled;\n }\n\n function afterGlvDepositCancellation(bytes32 /* key */, EventUtils.EventLogData memory /* glv deposit */, EventUtils.EventLogData memory /* eventData */) external {\n ++glvDepositCancellationCalled;\n }\n\n function afterGlvWithdrawalExecution(bytes32 /* key */, EventUtils.EventLogData memory /* glv withdrawal */, EventUtils.EventLogData memory /* eventData */) external {\n ++glvWithdrawalExecutionCalled;\n }\n\n function afterGlvWithdrawalCancellation(bytes32 /* key */, EventUtils.EventLogData memory /* glv withdrawal */, EventUtils.EventLogData memory /* eventData */) external {\n ++glvWithdrawalCancellationCalled;\n }\n}\n" + }, + "contracts/mock/MockEndpointV2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport { ILayerZeroEndpointV2, MessagingParams, MessagingReceipt, MessagingFee, Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { ExecutionState } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/EndpointV2ViewUpgradeable.sol\";\nimport { ILayerZeroReceiver } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol\";\nimport { SetConfigParam } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\";\nimport { MessagingContext } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingContext.sol\";\nimport { Packet } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol\";\nimport { OFTMsgCodec } from \"@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol\";\nimport { Origin } from \"@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol\";\nimport { Errors } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Errors.sol\";\nimport { GUID } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/GUID.sol\";\nimport { PacketV1Codec } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol\";\nimport { ExecutorOptions } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/libs/ExecutorOptions.sol\";\nimport { WorkerOptions } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/SendLibBase.sol\";\nimport { IExecutorFeeLib } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IExecutorFeeLib.sol\";\nimport { DVNOptions } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/DVNOptions.sol\";\nimport { UlnOptions } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/UlnOptions.sol\";\nimport { CalldataBytesLib } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol\";\nimport { EVMCallRequestV1, EVMCallComputeV1, ReadCodecV1 } from \"@layerzerolabs/oapp-evm/contracts/oapp/libs/ReadCodecV1.sol\";\nimport { MultichainReader } from \"../multichain/MultichainReader.sol\";\n\ncontract MockEndpointV2 is ILayerZeroEndpointV2, MessagingContext {\n using ExecutorOptions for bytes;\n using OFTMsgCodec for bytes;\n using OFTMsgCodec for bytes32;\n using OFTMsgCodec for address;\n using SafeCast for uint256;\n using CalldataBytesLib for bytes;\n\n bytes32 public constant EMPTY_PAYLOAD_HASH = bytes32(0);\n\n uint32 public immutable eid;\n mapping(address => address) public lzEndpointLookup;\n uint32 public readChannelId;\n\n mapping(address receiver => mapping(uint32 srcEid => mapping(bytes32 sender => uint64 nonce)))\n public lazyInboundNonce;\n mapping(address receiver => mapping(uint32 srcEid => mapping(bytes32 sender => mapping(uint64 inboundNonce => bytes32 payloadHash))))\n public inboundPayloadHash;\n mapping(address sender => mapping(uint32 dstEid => mapping(bytes32 receiver => uint64 nonce))) public outboundNonce;\n\n RelayerFeeConfig public relayerFeeConfig;\n ProtocolFeeConfig protocolFeeConfig;\n uint256 public verifierFee;\n\n struct ProtocolFeeConfig {\n uint256 zroFee;\n uint256 nativeBP;\n }\n\n struct RelayerFeeConfig {\n uint128 dstPriceRatio; // 10^10\n uint128 dstGasPriceInWei;\n uint128 dstNativeAmtCap;\n uint64 baseGas;\n uint64 gasPerByte;\n }\n\n uint8 internal constant _NOT_ENTERED = 1;\n uint8 internal constant _ENTERED = 2;\n uint8 internal _receive_entered_state = 1;\n modifier receiveNonReentrant() {\n require(_receive_entered_state == _NOT_ENTERED, \"LayerZeroMock: no receive reentrancy\");\n _receive_entered_state = _ENTERED;\n _;\n _receive_entered_state = _NOT_ENTERED;\n }\n\n event ValueTransferFailed(address indexed to, uint256 indexed quantity);\n\n constructor(uint32 _eid) {\n eid = _eid;\n // init config\n relayerFeeConfig = RelayerFeeConfig({\n dstPriceRatio: 1e10, // 1:1, same chain, same native coin\n dstGasPriceInWei: 1e10,\n dstNativeAmtCap: 1e19,\n baseGas: 100,\n gasPerByte: 1\n });\n protocolFeeConfig = ProtocolFeeConfig({ zroFee: 1e18, nativeBP: 1000 }); // BP 0.1\n verifierFee = 1e16;\n }\n\n function send(\n MessagingParams calldata _params,\n address _refundAddress\n ) public payable sendContext(_params.dstEid, msg.sender) returns (MessagingReceipt memory receipt) {\n if (_params.payInLzToken) revert Errors.LZ_LzTokenUnavailable();\n\n address lzEndpoint = lzEndpointLookup[_params.receiver.bytes32ToAddress()];\n require(lzEndpoint != address(0), \"LayerZeroMock: destination LayerZero Endpoint not found\");\n bool isReadMessage = _params.dstEid == readChannelId;\n\n // get the correct outbound nonce\n uint64 latestNonce = _outbound(msg.sender, _params.dstEid, _params.receiver);\n\n Packet memory packet = Packet({\n nonce: latestNonce,\n srcEid: eid,\n sender: msg.sender,\n dstEid: _params.dstEid,\n receiver: _params.receiver,\n guid: GUID.generate(latestNonce, eid, msg.sender, _params.dstEid, _params.receiver),\n message: _params.message\n });\n receipt.guid = packet.guid;\n receipt.nonce = packet.nonce;\n receipt.fee = _quote(_params, msg.sender);\n require(msg.value >= receipt.fee.nativeFee, \"LayerZeroMock: not enough native for fees\");\n\n // refund if they send too much\n uint256 amount = msg.value - receipt.fee.nativeFee;\n if (amount > 0) {\n (bool success, ) = _refundAddress.call{ value: amount }(\"\");\n require(success, \"LayerZeroMock: failed to refund\");\n }\n\n uint256 totalGas;\n uint256 dstAmount;\n (totalGas, dstAmount) = executeNativeAirDropAndReturnLzGas(_params.options);\n\n // TODO fix\n // composed calls with correct gas\n\n Origin memory origin = Origin({\n // Flip src and dst for read messages\n srcEid: isReadMessage ? packet.dstEid : packet.srcEid,\n sender: packet.sender.addressToBytes32(),\n nonce: packet.nonce\n });\n\n bytes32 payloadHash;\n {\n bytes memory payload = PacketV1Codec.encodePayload(packet);\n payloadHash = keccak256(payload);\n }\n\n bytes memory receiveMessage;\n if (isReadMessage) {\n receiveMessage = processLzReduce(_params.message);\n } else {\n receiveMessage = packet.message;\n }\n\n MockEndpointV2(lzEndpoint).receivePayload{ value: dstAmount }(\n origin,\n packet.receiver.bytes32ToAddress(),\n payloadHash,\n receiveMessage,\n totalGas,\n dstAmount,\n packet.guid\n );\n }\n\n function receivePayload(\n Origin calldata _origin,\n address _receiver,\n bytes32 _payloadHash,\n bytes calldata _message,\n uint256 _gas,\n uint256 _msgValue,\n bytes32 _guid\n ) external payable receiveNonReentrant {\n inboundPayloadHash[_receiver][_origin.srcEid][_origin.sender][_origin.nonce] = _payloadHash;\n if (_msgValue > 0) {\n ILayerZeroReceiver(_receiver).lzReceive{ value: _msgValue, gas: _gas }(\n _origin,\n _guid,\n _message,\n address(0),\n \"\"\n );\n } else {\n ILayerZeroReceiver(_receiver).lzReceive{ gas: _gas }(_origin, _guid, _message, address(0), \"\");\n }\n }\n\n function getExecutorFee(uint256 _payloadSize, bytes calldata _options) public view returns (uint256) {\n uint256 nativeFee;\n // 2) get Executor fee\n // a) decodeLzReceiveOption\n // b) decodeNativeDropOption\n // c) decodeLzComposeOption\n (uint256 totalDstAmount, uint256 totalGas) = _decodeExecutorOptions(_options);\n uint256 remoteGasTotal = relayerFeeConfig.dstGasPriceInWei * (relayerFeeConfig.baseGas + totalGas);\n nativeFee += totalDstAmount + remoteGasTotal;\n\n // tokenConversionRate = dstPrice / localPrice\n // basePrice = totalRemoteToken * tokenConversionRate\n uint256 basePrice = (nativeFee * relayerFeeConfig.dstPriceRatio) / 10 ** 10;\n\n // pricePerByte = (dstGasPriceInWei * gasPerBytes) * tokenConversionRate\n uint256 pricePerByte = ((relayerFeeConfig.dstGasPriceInWei *\n relayerFeeConfig.gasPerByte *\n relayerFeeConfig.dstPriceRatio) / 10 ** 10) * _payloadSize;\n\n return basePrice + pricePerByte;\n }\n\n function processLzReduce(bytes calldata message) internal view returns (bytes memory) {\n (, EVMCallRequestV1[] memory evmCallRequests, ) = ReadCodecV1.decode(message);\n uint256 numberOfRequests = evmCallRequests.length;\n bytes[] memory responses = new bytes[](numberOfRequests);\n for (uint256 i = 0; i < numberOfRequests; i++) {\n (, responses[i]) = evmCallRequests[i].to.staticcall(evmCallRequests[i].callData);\n }\n return MultichainReader(msg.sender).lzReduce(message, responses);\n }\n\n function _quote(\n MessagingParams calldata _params,\n address /*_sender*/\n ) internal view returns (MessagingFee memory messagingFee) {\n (bytes memory executorOptions, ) = UlnOptions.decode(_params.options);\n\n // 2) get Executor fee\n uint256 executorFee = this.getExecutorFee(_params.message.length, executorOptions);\n\n // 1) get Verifier fee\n // 3) get Treasury fee\n uint256 treasuryAndVerifierFee = _getTreasuryAndVerifierFees(executorFee, verifierFee);\n\n messagingFee.lzTokenFee = 0;\n messagingFee.nativeFee = executorFee + treasuryAndVerifierFee;\n }\n\n function _getTreasuryAndVerifierFees(uint256 _executorFee, uint256 _verifierFee) internal view returns (uint256) {\n return ((_executorFee + _verifierFee) * protocolFeeConfig.nativeBP) / 10000;\n }\n\n function _outbound(address _sender, uint32 _dstEid, bytes32 _receiver) internal returns (uint64 nonce) {\n unchecked {\n nonce = ++outboundNonce[_sender][_dstEid][_receiver];\n }\n }\n\n function setDestLzEndpoint(address destAddr, address lzEndpointAddr) external {\n lzEndpointLookup[destAddr] = lzEndpointAddr;\n }\n\n function setReadChannelId(uint32 _readChannelId) external {\n readChannelId = _readChannelId;\n }\n\n function _decodeExecutorOptions(\n bytes calldata _options\n ) internal view returns (uint256 dstAmount, uint256 totalGas) {\n if (_options.length == 0) {\n revert IExecutorFeeLib.Executor_NoOptions();\n }\n\n uint256 cursor = 0;\n totalGas = relayerFeeConfig.baseGas;\n\n while (cursor < _options.length) {\n (uint8 optionType, bytes calldata option, uint256 newCursor) = _options.nextExecutorOption(cursor);\n cursor = newCursor;\n\n if (optionType == ExecutorOptions.OPTION_TYPE_LZRECEIVE) {\n (uint128 gas, uint128 value) = ExecutorOptions.decodeLzReceiveOption(option);\n dstAmount += value;\n totalGas += gas;\n } else if (optionType == ExecutorOptions.OPTION_TYPE_NATIVE_DROP) {\n (uint128 nativeDropAmount, ) = ExecutorOptions.decodeNativeDropOption(option);\n dstAmount += nativeDropAmount;\n } else if (optionType == ExecutorOptions.OPTION_TYPE_LZCOMPOSE) {\n (, uint128 gas, uint128 value) = ExecutorOptions.decodeLzComposeOption(option);\n dstAmount += value;\n totalGas += gas;\n } else if (optionType == ExecutorOptions.OPTION_TYPE_LZREAD) {\n (uint128 gas, , uint128 value) = ExecutorOptions.decodeLzReadOption(option);\n dstAmount += value;\n totalGas += gas;\n } else {\n revert IExecutorFeeLib.Executor_UnsupportedOptionType(optionType);\n }\n }\n\n if (cursor != _options.length) revert IExecutorFeeLib.Executor_InvalidExecutorOptions(cursor);\n if (dstAmount > relayerFeeConfig.dstNativeAmtCap)\n revert IExecutorFeeLib.Executor_NativeAmountExceedsCap(dstAmount, relayerFeeConfig.dstNativeAmtCap);\n }\n\n function splitOptions(bytes calldata _options) internal pure returns (bytes memory, WorkerOptions[] memory) {\n (bytes memory executorOpts, bytes memory dvnOpts) = decode(_options);\n\n if (dvnOpts.length == 0) {\n return (executorOpts, new WorkerOptions[](0));\n }\n\n WorkerOptions[] memory workerOpts = new WorkerOptions[](1);\n workerOpts[0] = WorkerOptions(DVNOptions.WORKER_ID, dvnOpts);\n return (executorOpts, workerOpts);\n }\n\n function decode(\n bytes calldata _options\n ) internal pure returns (bytes memory executorOptions, bytes memory dvnOptions) {\n // at least 2 bytes for the option type, but can have no options\n if (_options.length < 2) revert UlnOptions.LZ_ULN_InvalidWorkerOptions(0);\n\n uint16 optionsType = uint16(bytes2(_options[0:2]));\n uint256 cursor = 2;\n\n // type3 options: [worker_option][worker_option]...\n // worker_option: [worker_id][option_size][option]\n // worker_id: uint8, option_size: uint16, option: bytes\n if (optionsType == UlnOptions.TYPE_3) {\n unchecked {\n uint256 start = cursor;\n uint8 lastWorkerId; // worker_id starts from 1, so 0 is an invalid worker_id\n\n // heuristic: we assume that the options are mostly EXECUTOR options only\n // checking the workerID can reduce gas usage for most cases\n while (cursor < _options.length) {\n uint8 workerId = uint8(bytes1(_options[cursor:cursor + 1]));\n if (workerId == 0) revert UlnOptions.LZ_ULN_InvalidWorkerId(0);\n\n // workerId must equal to the lastWorkerId for the first option\n // so it is always skipped in the first option\n // this operation slices out options whenever the scan finds a different workerId\n if (lastWorkerId == 0) {\n lastWorkerId = workerId;\n } else if (workerId != lastWorkerId) {\n bytes calldata op = _options[start:cursor]; // slice out the last worker's options\n (executorOptions, dvnOptions) = _insertWorkerOptions(\n executorOptions,\n dvnOptions,\n lastWorkerId,\n op\n );\n\n // reset the start cursor and lastWorkerId\n start = cursor;\n lastWorkerId = workerId;\n }\n\n ++cursor; // for workerId\n\n uint16 size = uint16(bytes2(_options[cursor:cursor + 2]));\n if (size == 0) revert UlnOptions.LZ_ULN_InvalidWorkerOptions(cursor);\n cursor += size + 2;\n }\n\n // the options length must be the same as the cursor at the end\n if (cursor != _options.length) revert UlnOptions.LZ_ULN_InvalidWorkerOptions(cursor);\n\n // if we have reached the end of the options and the options are not empty\n // we need to process the last worker's options\n if (_options.length > 2) {\n bytes calldata op = _options[start:cursor];\n (executorOptions, dvnOptions) = _insertWorkerOptions(executorOptions, dvnOptions, lastWorkerId, op);\n }\n }\n } else {\n executorOptions = decodeLegacyOptions(optionsType, _options);\n }\n }\n\n function _insertWorkerOptions(\n bytes memory _executorOptions,\n bytes memory _dvnOptions,\n uint8 _workerId,\n bytes calldata _newOptions\n ) private pure returns (bytes memory, bytes memory) {\n if (_workerId == ExecutorOptions.WORKER_ID) {\n _executorOptions = _executorOptions.length == 0\n ? _newOptions\n : abi.encodePacked(_executorOptions, _newOptions);\n } else if (_workerId == DVNOptions.WORKER_ID) {\n _dvnOptions = _dvnOptions.length == 0 ? _newOptions : abi.encodePacked(_dvnOptions, _newOptions);\n } else {\n revert UlnOptions.LZ_ULN_InvalidWorkerId(_workerId);\n }\n return (_executorOptions, _dvnOptions);\n }\n\n function decodeLegacyOptions(\n uint16 _optionType,\n bytes calldata _options\n ) internal pure returns (bytes memory executorOptions) {\n if (_optionType == UlnOptions.TYPE_1) {\n if (_options.length != 34) revert UlnOptions.LZ_ULN_InvalidLegacyType1Option();\n\n // execution gas\n uint128 executionGas = uint256(bytes32(_options[2:2 + 32])).toUint128();\n\n // dont use the encode function in the ExecutorOptions lib for saving gas by calling abi.encodePacked once\n // the result is a lzReceive option: [executor_id][option_size][option_type][execution_gas]\n // option_type: uint8, execution_gas: uint128\n // option_size = len(option_type) + len(execution_gas) = 1 + 16 = 17\n executorOptions = abi.encodePacked(\n ExecutorOptions.WORKER_ID,\n uint16(17), // 16 + 1, 16 for option_length, + 1 for option_type\n ExecutorOptions.OPTION_TYPE_LZRECEIVE,\n executionGas\n );\n } else if (_optionType == UlnOptions.TYPE_2) {\n // receiver size <= 32\n if (_options.length <= 66 || _options.length > 98) revert UlnOptions.LZ_ULN_InvalidLegacyType2Option();\n\n // execution gas\n uint128 executionGas = uint256(bytes32(_options[2:2 + 32])).toUint128();\n\n // nativeDrop (amount + receiver)\n uint128 amount = uint256(bytes32(_options[34:34 + 32])).toUint128(); // offset 2 + 32\n bytes32 receiver;\n unchecked {\n uint256 receiverLen = _options.length - 66; // offset 2 + 32 + 32\n receiver = bytes32(_options[66:]);\n receiver = receiver >> (8 * (32 - receiverLen)); // padding 0 to the left\n }\n\n // dont use the encode function in the ExecutorOptions lib for saving gas by calling abi.encodePacked once\n // the result has one lzReceive option and one nativeDrop option:\n // [executor_id][lzReceive_option_size][option_type][execution_gas] +\n // [executor_id][nativeDrop_option_size][option_type][nativeDrop_amount][receiver]\n // option_type: uint8, execution_gas: uint128, nativeDrop_amount: uint128, receiver: bytes32\n // lzReceive_option_size = len(option_type) + len(execution_gas) = 1 + 16 = 17\n // nativeDrop_option_size = len(option_type) + len(nativeDrop_amount) + len(receiver) = 1 + 16 + 32 = 49\n executorOptions = abi.encodePacked(\n ExecutorOptions.WORKER_ID,\n uint16(17), // 16 + 1, 16 for option_length, + 1 for option_type\n ExecutorOptions.OPTION_TYPE_LZRECEIVE,\n executionGas,\n ExecutorOptions.WORKER_ID,\n uint16(49), // 48 + 1, 32 + 16 for option_length, + 1 for option_type\n ExecutorOptions.OPTION_TYPE_NATIVE_DROP,\n amount,\n receiver\n );\n } else {\n revert UlnOptions.LZ_ULN_UnsupportedOptionType(_optionType);\n }\n }\n\n // NOT IMPLEMENTING\n function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external {}\n\n function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external {}\n\n mapping(address from => mapping(address to => mapping(bytes32 guid => mapping(uint16 index => bytes32 messageHash))))\n public composeQueue;\n\n function defaultReceiveLibrary(uint32 /*_eid*/) external pure returns (address) {\n return address(0);\n }\n\n function defaultReceiveLibraryTimeout(uint32 /*_eid*/) external pure returns (address lib, uint256 expiry) {\n return (address(0), 0);\n }\n\n function defaultSendLibrary(uint32 /*_eid*/) external pure returns (address) {\n return address(0);\n }\n\n function executable(Origin calldata /*_origin*/, address /*receiver*/) external pure returns (ExecutionState) {\n return ExecutionState.NotExecutable;\n }\n\n function getConfig(\n address /*_oapp*/,\n address /*_lib*/,\n uint32 /*_eid*/,\n uint32 /*_configType*/\n ) external pure returns (bytes memory config) {\n return bytes(\"0x\");\n }\n\n function getReceiveLibrary(\n address /*receiver*/,\n uint32 /*_eid*/\n ) external pure returns (address lib, bool isDefault) {\n return (address(0), false);\n }\n\n function getRegisteredLibraries() external pure returns (address[] memory) {\n address[] memory addresses = new address[](1);\n addresses[0] = address(0);\n return addresses;\n }\n\n function getSendLibrary(address /*_sender*/, uint32 /*_eid*/) external pure returns (address lib) {\n return address(0);\n }\n\n function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64) {\n return lazyInboundNonce[_receiver][_srcEid][_sender];\n }\n\n function isDefaultSendLibrary(address /*_sender*/, uint32 /*_eid*/) external pure returns (bool) {\n return false;\n }\n\n function isRegisteredLibrary(address /*_lib*/) external pure returns (bool) {\n return false;\n }\n\n function isSupportedEid(uint32 /*_eid*/) external pure returns (bool) {\n return false;\n }\n\n function lzCompose(\n address /*_from,*/,\n address /*_to,*/,\n bytes32 /*_guid,*/,\n uint16 /*_index,*/,\n bytes calldata /*_message,*/,\n bytes calldata /*_extraData*/\n ) external payable {}\n\n function lzReceive(\n Origin calldata /*_origin,*/,\n address /*_receiver,*/,\n bytes32 /*_guid,*/,\n bytes calldata /*_message,*/,\n bytes calldata /*_extraData*/\n ) external payable {}\n\n function lzToken() external pure returns (address) {\n return address(0);\n }\n\n function nativeToken() external pure returns (address) {\n return address(0);\n }\n\n function nextGuid(\n address /*_sender,*/,\n uint32 /*_dstEid,*/,\n bytes32 /*_receiver*/\n ) external pure returns (bytes32) {\n return 0;\n }\n\n function nilify(\n address /*_oapp,*/,\n uint32 /*_srcEid,*/,\n bytes32 /*_sender,*/,\n uint64 /*_nonce,*/,\n bytes32 /*_payloadHash*/\n ) external {}\n\n function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory) {\n return _quote(_params, _sender);\n }\n\n mapping(address receiver => mapping(uint32 srcEid => Timeout)) public receiveLibraryTimeout;\n\n function registerLibrary(address /*_lib*/) public {}\n\n function sendCompose(address, /*_to*/ bytes32, /*_guid*/ uint16, /*_index*/ bytes calldata /*_message*/) external {}\n\n function setConfig(address, /*_oapp*/ address, /*_lib*/ SetConfigParam[] calldata /*_params*/) external {}\n\n function setDefaultReceiveLibrary(uint32 /*_eid*/, address /*_newLib*/, uint256 /*_gracePeriod*/) external {}\n\n function setDefaultReceiveLibraryTimeout(uint32 /*_eid*/, address /*_lib*/, uint256 /*_expiry*/) external {}\n\n function setDefaultSendLibrary(uint32 /*_eid*/, address /*_newLib*/) external {}\n\n function setDelegate(address /*_delegate*/) external {}\n\n function setLzToken(address /*_lzToken*/) external {}\n\n function setReceiveLibrary(\n address,\n /*_oapp*/ uint32,\n /*_eid*/ address,\n /*_newLib*/ uint256 /*_gracePeriod*/\n ) external {}\n\n function setReceiveLibraryTimeout(\n address,\n /*_oapp*/ uint32,\n /*_eid*/ address,\n /*_lib*/ uint256 /*_gracePeriod*/\n ) external {}\n\n function setSendLibrary(address, /*_oapp*/ uint32, /*_eid*/ address /*_newLib*/) external {}\n\n function skip(address, /*_oapp*/ uint32, /*_srcEid*/ bytes32, /*_sender*/ uint64 /*_nonce*/) external {}\n\n function verifiable(\n Origin calldata /*_origin*/,\n address /*_receiver*/,\n address /*_receiveLib*/,\n bytes32 /*_payloadHash*/\n ) external pure returns (bool) {\n return false;\n }\n\n function verify(Origin calldata /*origin*/, address /*_receiver*/, bytes32 /*_payloadHash*/) external {}\n\n // Helper Functions\n function executeNativeAirDropAndReturnLzGas(\n bytes calldata _options\n ) public returns (uint256 totalGas, uint256 dstAmount) {\n (bytes memory executorOpts, ) = decode(_options);\n return this._executeNativeAirDropAndReturnLzGas(executorOpts);\n }\n\n function _executeNativeAirDropAndReturnLzGas(\n bytes calldata _options\n ) public returns (uint256 totalGas, uint256 dstAmount) {\n if (_options.length == 0) {\n revert IExecutorFeeLib.Executor_NoOptions();\n }\n\n uint256 cursor = 0;\n while (cursor < _options.length) {\n (uint8 optionType, bytes calldata option, uint256 newCursor) = _options.nextExecutorOption(cursor);\n cursor = newCursor;\n\n if (optionType == ExecutorOptions.OPTION_TYPE_LZRECEIVE) {\n (uint128 gas, uint128 value) = ExecutorOptions.decodeLzReceiveOption(option);\n totalGas += gas;\n dstAmount += value;\n } else if (optionType == ExecutorOptions.OPTION_TYPE_NATIVE_DROP) {\n (uint128 nativeDropAmount, bytes32 receiver) = ExecutorOptions.decodeNativeDropOption(option);\n (bool success, ) = receiver.bytes32ToAddress().call{ value: nativeDropAmount }(\"\");\n if (!success) {\n emit ValueTransferFailed(receiver.bytes32ToAddress(), nativeDropAmount);\n }\n } else if (optionType == ExecutorOptions.OPTION_TYPE_LZREAD) {\n (uint128 gas, , uint128 value) = ExecutorOptions.decodeLzReadOption(option);\n totalGas += gas;\n dstAmount += value;\n } else {\n revert IExecutorFeeLib.Executor_UnsupportedOptionType(optionType);\n }\n }\n\n if (cursor != _options.length) revert IExecutorFeeLib.Executor_InvalidExecutorOptions(cursor);\n }\n\n function _initializable(\n Origin calldata _origin,\n address _receiver,\n uint64 _lazyInboundNonce\n ) internal view returns (bool) {\n return\n _lazyInboundNonce > 0 || // allowInitializePath already checked\n ILayerZeroReceiver(_receiver).allowInitializePath(_origin);\n }\n\n /// @dev bytes(0) payloadHash can never be submitted\n function _verifiable(\n Origin calldata _origin,\n address _receiver,\n uint64 _lazyInboundNonce\n ) internal view returns (bool) {\n return\n _origin.nonce > _lazyInboundNonce || // either initializing an empty slot or reverifying\n inboundPayloadHash[_receiver][_origin.srcEid][_origin.sender][_origin.nonce] != EMPTY_PAYLOAD_HASH; // only allow reverifying if it hasn't been executed\n }\n\n // ========================= VIEW FUNCTIONS FOR OFFCHAIN ONLY =========================\n // Not involved in any state transition function.\n // ====================================================================================\n function initializable(Origin calldata _origin, address _receiver) external view returns (bool) {\n return _initializable(_origin, _receiver, lazyInboundNonce[_receiver][_origin.srcEid][_origin.sender]);\n }\n\n function verifiable(Origin calldata _origin, address _receiver) external view returns (bool) {\n return _verifiable(_origin, _receiver, lazyInboundNonce[_receiver][_origin.srcEid][_origin.sender]);\n }\n\n /// @dev called when the endpoint checks if the msgLib attempting to verify the msg is the configured msgLib of the Oapp\n /// @dev this check provides the ability for Oapp to lock in a trusted msgLib\n /// @dev it will fist check if the msgLib is the currently configured one. then check if the msgLib is the one in grace period of msgLib versioning upgrade\n function isValidReceiveLibrary(\n address /*_receiver*/,\n uint32 /*_srcEid*/,\n address /*_actualReceiveLib*/\n ) public pure returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/mock/MockFeeDistributor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@layerzerolabs/oft-evm/contracts/OFTCore.sol\";\n\nimport \"../fee/FeeDistributorUtils.sol\";\nimport \"../fee/FeeDistributorVault.sol\";\nimport \"../fee/FeeHandler.sol\";\nimport \"../multichain/MultichainReader.sol\";\nimport \"../oracle/ChainlinkPriceFeedUtils.sol\";\nimport \"../claim/ClaimUtils.sol\";\nimport \"../v1/IRewardTrackerV1.sol\";\nimport \"../v1/IRewardDistributorV1.sol\";\nimport \"../v1/IVesterV1.sol\";\nimport \"../v1/IMintable.sol\";\n\ncontract MockFeeDistributor is ReentrancyGuard, RoleModule {\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // constant and immutable variables are internal to reduce the contract size\n bytes internal constant EMPTY_BYTES = \"\";\n\n bytes32 internal constant GMX = keccak256(abi.encode(\"GMX\"));\n bytes32 internal constant EXTENDED_GMX_TRACKER = keccak256(abi.encode(\"EXTENDED_GMX_TRACKER\"));\n bytes32 internal constant DATASTORE = keccak256(abi.encode(\"DATASTORE\"));\n bytes32 internal constant TREASURY = keccak256(abi.encode(\"TREASURY\"));\n bytes32 internal constant LAYERZERO_OFT = keccak256(abi.encode(\"LAYERZERO_OFT\"));\n bytes32 internal constant CHAINLINK = keccak256(abi.encode(\"CHAINLINK\"));\n bytes32 internal constant ESGMX_VESTER = keccak256(abi.encode(\"ESGMX_VESTER\"));\n\n uint256 internal constant mockChainId = 40000;\n\n FeeDistributorVault internal immutable feeDistributorVault;\n FeeHandler internal immutable feeHandler;\n DataStore internal immutable dataStore;\n DataStore internal immutable dataStoreForOracle;\n EventEmitter internal immutable eventEmitter;\n MultichainReader internal immutable multichainReader;\n\n address internal immutable claimVault;\n address internal immutable gmx;\n address internal immutable gmxForOracle;\n address internal immutable esGmx;\n address internal immutable wnt;\n\n struct MockVariables {\n DataStore dataStoreForOracle;\n address gmxForOracle;\n }\n\n receive() external payable {}\n\n constructor(\n RoleStore _roleStore,\n FeeDistributorVault _feeDistributorVault,\n FeeHandler _feeHandler,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n MultichainReader _multichainReader,\n address _claimVault,\n address _gmx,\n address _esGmx,\n address _wnt,\n MockVariables memory _mockVariables\n ) RoleModule(_roleStore) {\n feeDistributorVault = _feeDistributorVault;\n feeHandler = _feeHandler;\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n multichainReader = _multichainReader;\n claimVault = _claimVault;\n gmx = _gmx;\n esGmx = _esGmx;\n wnt = _wnt;\n\n dataStoreForOracle = _mockVariables.dataStoreForOracle;\n gmxForOracle = _mockVariables.gmxForOracle;\n }\n\n // @dev initiate the weekly fee distribution process\n //\n // The fee distribution process relies on the premise that this function is executed synchronously\n // across all chains to which it is deployed and is executed for the same fee distribution period\n //\n // In cases in which a chain encounters downtime or a keeper experiences issues, a contingency\n // should be in place to ensure the fee distribution is completed without issues\n function initiateDistribute() external nonReentrant onlyFeeDistributionKeeper {\n // validate that the FEE_RECEIVER address stored in dataStore = FeeDistributorVault\n address feeReceiver = _getAddress(Keys.FEE_RECEIVER);\n if (feeReceiver != address(feeDistributorVault)) {\n revert Errors.InvalidFeeReceiver(feeReceiver);\n }\n\n // validate distribution state and that distribution is not yet completed for the current week\n _validateDistributionState(DistributionState.None);\n _validateDistributionNotCompleted();\n\n // reset referral rewards deposited for WNT and esGMX to 0 for the current week's distribution\n _setUint(Keys2.feeDistributorReferralRewardsDepositedKey(wnt), 0);\n _setUint(Keys2.feeDistributorReferralRewardsDepositedKey(esGmx), 0);\n\n // populate readRequestInputs and extraOptionsInputs param used for cross chain LZRead request\n uint256[] memory chainIds = FeeDistributorUtils.retrieveChainIds(dataStore);\n uint256 chainIdsLength = chainIds.length;\n MultichainReaderUtils.ReadRequestInputs[]\n memory readRequestInputs = new MultichainReaderUtils.ReadRequestInputs[]((chainIdsLength - 1) * 3);\n uint256 targetChainIndex;\n for (uint256 i; i < chainIdsLength; i++) {\n uint256 chainId = chainIds[i];\n address extendedGmxTracker = _getAddressInfoForChain(chainId, EXTENDED_GMX_TRACKER);\n\n if (chainId == mockChainId) {\n uint256 feeAmountGmxCurrentChain = _getUint(Keys.withdrawableBuybackTokenAmountKey(gmx)) +\n _getFeeDistributorVaultBalance(gmx);\n uint256 stakedGmx = IERC20(extendedGmxTracker).totalSupply();\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(chainId), feeAmountGmxCurrentChain);\n _setUint(Keys2.feeDistributorStakedGmxKey(chainId), stakedGmx);\n continue;\n }\n\n address gmxTargetChain = _getAddressInfoForChain(chainId, GMX);\n uint32 layerZeroChainId = uint32(_getUint(Keys2.feeDistributorLayerZeroChainIdKey(chainId)));\n uint256 readRequestIndex = targetChainIndex * 3;\n readRequestInputs[readRequestIndex] = _setReadRequestInput(\n layerZeroChainId,\n _getAddressInfoForChain(chainId, DATASTORE),\n abi.encodeWithSelector(\n DataStore.getUint.selector,\n Keys.withdrawableBuybackTokenAmountKey(gmxTargetChain)\n )\n );\n readRequestIndex++;\n\n readRequestInputs[readRequestIndex] = _setReadRequestInput(\n layerZeroChainId,\n gmxTargetChain,\n abi.encodeWithSelector(IERC20.balanceOf.selector, _getAddressInfoForChain(chainId, Keys.FEE_RECEIVER))\n );\n readRequestIndex++;\n\n readRequestInputs[readRequestIndex] = _setReadRequestInput(\n layerZeroChainId,\n extendedGmxTracker,\n abi.encodeWithSelector(IERC20.totalSupply.selector)\n );\n targetChainIndex++;\n }\n\n MultichainReaderUtils.ExtraOptionsInputs memory extraOptionsInputs;\n extraOptionsInputs.gasLimit = uint128(_getUint(Keys2.FEE_DISTRIBUTOR_GAS_LIMIT));\n extraOptionsInputs.returnDataSize = ((uint32(chainIdsLength) - 1) * 96) + 8;\n\n _setDistributionState(uint256(DistributionState.Initiated));\n\n // calculate native token fee required and execute multichainReader.sendReadRequests LZRead request\n MessagingFee memory messagingFee = multichainReader.quoteReadFee(readRequestInputs, extraOptionsInputs);\n multichainReader.sendReadRequests{ value: messagingFee.nativeFee }(readRequestInputs, extraOptionsInputs);\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"numberOfChainsReadRequests\", chainIdsLength - 1);\n _setUintItem(eventData, 1, \"messagingFee.nativeFee\", messagingFee.nativeFee);\n _emitFeeDistributionEvent(eventData, \"FeeDistributionInitiated\");\n }\n\n // @dev receive and process the LZRead request received data and bridge GMX to other chains if necessary\n // @param guid unused parameter that represents the unique idenfifier for the LZRead request\n // @param receivedData MultichainReaderUtils.ReceivedData the LZRead request received data\n function processLzReceive(\n bytes32 /*guid*/,\n MultichainReaderUtils.ReceivedData calldata receivedData\n ) external onlyMultichainReader {\n // validate the distribution state and that the LZRead response is within the acceptable time limit\n _validateDistributionState(DistributionState.Initiated);\n _validateReadResponseTimestamp(receivedData.timestamp);\n\n // withdraw any GMX fees remaining in the feeHandler\n feeHandler.withdrawFees(gmx);\n\n // set the current chain and LZRead response fee amounts, staked GMX amounts, timestamp and current chain WNT price\n uint256[] memory chainIds = FeeDistributorUtils.retrieveChainIds(dataStore);\n uint256[] memory feeAmountsGmx = _createUintArray(chainIds.length);\n uint256[] memory stakedAmountsGmx = _createUintArray(chainIds.length);\n uint256 feeAmountGmxCurrentChain = _getUint(Keys2.feeDistributorFeeAmountGmxKey(mockChainId));\n uint256 stakedGmxCurrentChain = _getUint(Keys2.feeDistributorStakedGmxKey(mockChainId));\n uint256 totalFeeAmountGmx;\n uint256 totalStakedGmx;\n uint256 currentChainIndex;\n uint256 targetChainIndex;\n for (uint256 i; i < chainIds.length; i++) {\n uint256 chainId = chainIds[i];\n\n if (chainId == mockChainId) {\n feeAmountsGmx[i] = feeAmountGmxCurrentChain;\n stakedAmountsGmx[i] = stakedGmxCurrentChain;\n totalFeeAmountGmx += feeAmountGmxCurrentChain;\n totalStakedGmx += stakedGmxCurrentChain;\n currentChainIndex = i;\n continue;\n }\n (uint256 feeAmountGmx, uint256 stakedGmx) = _decodeReadData(receivedData.readData, targetChainIndex);\n feeAmountsGmx[i] = feeAmountGmx;\n stakedAmountsGmx[i] = stakedGmx;\n totalFeeAmountGmx += feeAmountGmx;\n totalStakedGmx += stakedGmx;\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(chainId), feeAmountGmx);\n _setUint(Keys2.feeDistributorStakedGmxKey(chainId), stakedGmx);\n targetChainIndex++;\n }\n _setUint(Keys2.FEE_DISTRIBUTOR_TOTAL_FEE_AMOUNT_GMX, totalFeeAmountGmx);\n _setUint(Keys2.FEE_DISTRIBUTOR_TOTAL_STAKED_GMX, totalStakedGmx);\n _setUint(Keys2.FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP, receivedData.timestamp);\n _setTokenPrices();\n\n uint256 requiredGmxAmount = Precision.mulDiv(totalFeeAmountGmx, stakedGmxCurrentChain, totalStakedGmx);\n uint256 totalGmxBridgedOut;\n // validate that the this chain has sufficient GMX to distribute fees\n if (feeAmountGmxCurrentChain >= requiredGmxAmount) {\n // only attempt to bridge to other chains if this chain has a surplus of GMX\n if (feeAmountGmxCurrentChain > requiredGmxAmount) {\n // Call the internal bridging function\n totalGmxBridgedOut = _calculateAndBridgeGmx(\n chainIds,\n totalFeeAmountGmx,\n stakedAmountsGmx,\n totalStakedGmx,\n feeAmountsGmx,\n currentChainIndex\n );\n\n uint256 newFeeAmountGmxCurrentChain = feeAmountGmxCurrentChain - totalGmxBridgedOut;\n // validate that the amount bridged does not result in a GMX fee amount deficit on the current chain\n if (requiredGmxAmount > newFeeAmountGmxCurrentChain) {\n revert Errors.AttemptedBridgeAmountTooHigh(\n requiredGmxAmount,\n feeAmountGmxCurrentChain,\n totalGmxBridgedOut\n );\n }\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(mockChainId), newFeeAmountGmxCurrentChain);\n }\n _setDistributionState(uint256(DistributionState.BridgingCompleted));\n } else {\n _setDistributionState(uint256(DistributionState.ReadDataReceived));\n }\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"feeAmountGmxCurrentChain\", feeAmountGmxCurrentChain);\n _setUintItem(eventData, 1, \"totalGmxBridgedOut\", totalGmxBridgedOut);\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"receivedData\", abi.encode(receivedData));\n _emitFeeDistributionEvent(eventData, \"FeeDistributionDataReceived\");\n }\n\n // @dev function executed via an automated Gelato transaction when bridged GMX is received on this chain\n function bridgedGmxReceived() external nonReentrant onlyFeeDistributionKeeper {\n _validateDistributionState(DistributionState.ReadDataReceived);\n _validateReadResponseTimestamp(_getUint(Keys2.FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP));\n _validateDistributionNotCompleted();\n\n uint256 totalFeeAmountGmx = _getUint(Keys2.FEE_DISTRIBUTOR_TOTAL_FEE_AMOUNT_GMX);\n uint256 stakedGmxCurrentChain = _getUint(Keys2.feeDistributorStakedGmxKey(mockChainId));\n uint256 totalStakedGmx = _getUint(Keys2.FEE_DISTRIBUTOR_TOTAL_STAKED_GMX);\n uint256 requiredGmxAmount = Precision.mulDiv(totalFeeAmountGmx, stakedGmxCurrentChain, totalStakedGmx);\n uint256 origFeeAmountGmxCurrentChain = _getUint(Keys2.feeDistributorFeeAmountGmxKey(mockChainId));\n\n // the gross amount of GMX that should be received, before taking into account slippage\n uint256 grossGmxReceived = requiredGmxAmount - origFeeAmountGmxCurrentChain;\n // the slippage factor used when bridging to account for bridging fees and potential slippage\n uint256 slippageFactor = _getUint(Keys2.feeDistributorBridgeSlippageFactorKey(mockChainId));\n // calculate the minimum acceptable amount of bridged GMX received, taking into account allowed slippage\n uint256 minGmxReceived = Precision.applyFactor(grossGmxReceived, slippageFactor);\n // the minimum allowed GMX amount after bridging, taking into account slippage\n uint256 minRequiredGmxAmount = origFeeAmountGmxCurrentChain + minGmxReceived;\n // retrieve the current GMX available to distribute now that bridging has been completed\n uint256 feeAmountGmxCurrentChain = _getFeeDistributorVaultBalance(gmx);\n\n // if the calculated amount doesn't meet the min bridging requirement, revert\n if (feeAmountGmxCurrentChain < minRequiredGmxAmount) {\n revert Errors.BridgedAmountNotSufficient(minRequiredGmxAmount, feeAmountGmxCurrentChain);\n }\n\n // now that the GMX available to distribute has been validated, update in dataStore and update DistributionState\n _setUint(Keys2.feeDistributorFeeAmountGmxKey(mockChainId), feeAmountGmxCurrentChain);\n _setDistributionState(uint256(DistributionState.BridgingCompleted));\n\n // infer the bridged GMX received - note that it is technically possible for this value to not match the actual\n // bridged GMX received if for example, GMX is sent to the FeeDistributorVault from another source or GMX fees\n // are withdrawn from the FeeHandler after processLzReceive() is executed but before this function is executed\n uint256 gmxReceived = feeAmountGmxCurrentChain - origFeeAmountGmxCurrentChain;\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"gmxReceived\", gmxReceived);\n _setUintItem(eventData, 1, \"feeAmountGmxCurrentChain\", feeAmountGmxCurrentChain);\n _emitFeeDistributionEvent(eventData, \"FeeDistributionBridgedGmxReceived\");\n }\n\n // @dev complete the fee distribution calculations, token transfers and if necessary bridge GMX cross-chain\n // @param wntReferralRewardsInUsd the total WNT referral rewards in USD\n // @param esGmxForReferralRewards the total esGMX to be distributed for referral rewards\n // @param feesV1Usd the total V1 fees in USD\n // @param feesV2Usd the total V2 fees in USD\n function distribute(\n uint256 wntReferralRewardsInUsd,\n uint256 esGmxForReferralRewards,\n uint256 feesV1Usd,\n uint256 feesV2Usd\n ) external nonReentrant onlyFeeDistributionKeeper {\n // validate that the TREASURY address stored in dataStore is not a zero address\n address treasuryAddress = _getAddressInfo(TREASURY);\n if (treasuryAddress == address(0)) {\n revert Errors.ZeroTreasuryAddress();\n }\n\n // validate the distribution states, LZRead response timestamp and distribution has not yet been completed\n _validateDistributionState(DistributionState.BridgingCompleted);\n _validateReadResponseTimestamp(_getUint(Keys2.FEE_DISTRIBUTOR_READ_RESPONSE_TIMESTAMP));\n _validateDistributionNotCompleted();\n\n // withdraw any WNT fees remaining in the feeHandler\n feeHandler.withdrawFees(wnt);\n\n // calculate WNT costs and transfer to appropriate addresses\n (\n uint256 wntForKeepers,\n uint256 wntForChainlink,\n uint256 wntForTreasury,\n uint256 wntForReferralRewards\n ) = _calculateAndTransferWntCosts(wntReferralRewardsInUsd, feesV1Usd, feesV2Usd);\n\n // set the total fees in USD and referral reward amounts\n _setUint(Keys2.feeDistributorFeeAmountUsdKey(1), feesV1Usd);\n _setUint(Keys2.feeDistributorFeeAmountUsdKey(2), feesV2Usd);\n _setUint(Keys2.feeDistributorReferralRewardsAmountKey(wnt), wntForReferralRewards);\n _setUint(Keys2.feeDistributorReferralRewardsAmountKey(esGmx), esGmxForReferralRewards);\n _setUint(Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_TIMESTAMP, block.timestamp);\n _setDistributionState(uint256(DistributionState.None));\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(7);\n _setUintItem(eventData, 0, \"feesV1Usd\", feesV1Usd);\n _setUintItem(eventData, 1, \"feesV2Usd\", feesV2Usd);\n _setUintItem(eventData, 2, \"wntForKeepers\", wntForKeepers);\n _setUintItem(eventData, 3, \"wntForChainlink\", wntForChainlink);\n _setUintItem(eventData, 4, \"wntForTreasury\", wntForTreasury);\n _setUintItem(eventData, 5, \"wntForReferralRewards\", wntForReferralRewards);\n _setUintItem(eventData, 6, \"esGmxForReferralRewards\", esGmxForReferralRewards);\n _emitFeeDistributionEvent(eventData, \"FeeDistributionCompleted\");\n }\n\n // @dev deposit the calculated referral rewards in the ClaimVault for the specified accounts\n // @param token the token in which the referral rewards will be sent\n // @param distributionId the distribution id\n // @param params array of referral rewards deposit parameters\n function depositReferralRewards(\n address token,\n uint256 distributionId,\n ClaimUtils.DepositParam[] calldata params\n ) external nonReentrant onlyFeeDistributionKeeper {\n // validate the distribution state and that the accounts and amounts arrays are valid lengths\n _validateDistributionState(DistributionState.None);\n\n uint256 tokensForReferralRewards = _getUint(Keys2.feeDistributorReferralRewardsAmountKey(token));\n uint256 cumulativeDepositAmount = _getUint(Keys2.feeDistributorReferralRewardsDepositedKey(token));\n if (token == esGmx) {\n // validate the esGMX amount is valid and that there are sufficient esGMX in the feeDistributorVault\n uint256 maxEsGmxReferralRewards = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_ESGMX_AMOUNT);\n if (tokensForReferralRewards > maxEsGmxReferralRewards) {\n revert Errors.MaxEsGmxReferralRewardsAmountExceeded(tokensForReferralRewards, maxEsGmxReferralRewards);\n }\n\n uint256 vaultEsGmxBalance = _getFeeDistributorVaultBalance(esGmx);\n uint256 esGmxToBeDeposited = tokensForReferralRewards - cumulativeDepositAmount;\n if (esGmxToBeDeposited > vaultEsGmxBalance) {\n IMintable(esGmx).mint(address(feeDistributorVault), esGmxToBeDeposited - vaultEsGmxBalance);\n }\n\n // update esGMX bonus reward amounts for each account in the vester contract\n for (uint256 i; i < params.length; i++) {\n ClaimUtils.DepositParam memory param = params[i];\n\n address vester = _getAddressInfo(ESGMX_VESTER);\n uint256 totalEsGmxRewards = IVester(vester).bonusRewards(param.account) + param.amount;\n IVester(vester).setBonusRewards(param.account, totalEsGmxRewards);\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(2);\n _setUintItem(eventData, 0, \"amount\", param.amount);\n _setUintItem(eventData, 1, \"totalEsGmxRewards\", totalEsGmxRewards);\n\n eventEmitter.emitEventLog1(\"TotalEsGmxRewardsIncreased\", Cast.toBytes32(param.account), eventData);\n }\n } else if (token != wnt) {\n revert Errors.InvalidReferralRewardToken(token);\n }\n\n uint256 totalTransferAmount = ClaimUtils.incrementClaims(\n dataStore,\n eventEmitter,\n token,\n distributionId,\n params\n );\n _transferOut(token, claimVault, totalTransferAmount);\n dataStore.incrementUint(Keys.totalClaimableFundsAmountKey(token), totalTransferAmount);\n\n ClaimUtils._validateTotalClaimableFundsAmount(dataStore, token, claimVault);\n\n // validate that the cumulative referral rewards deposited is not greater than the total calculated amount\n cumulativeDepositAmount += totalTransferAmount;\n if (cumulativeDepositAmount > tokensForReferralRewards) {\n revert Errors.MaxReferralRewardsExceeded(token, cumulativeDepositAmount, tokensForReferralRewards);\n }\n\n _setUint(Keys2.feeDistributorReferralRewardsDepositedKey(token), cumulativeDepositAmount);\n }\n\n function _calculateAndBridgeGmx(\n uint256[] memory chainIds,\n uint256 totalFeeAmountGmx,\n uint256[] memory stakedAmountsGmx,\n uint256 totalStakedGmx,\n uint256[] memory feeAmountsGmx,\n uint256 currentChainIndex\n ) internal returns (uint256) {\n uint256 chainIdsLength = chainIds.length;\n uint256[] memory target = new uint256[](chainIdsLength);\n for (uint256 i; i < chainIdsLength; i++) {\n target[i] = Precision.mulDiv(totalFeeAmountGmx, stakedAmountsGmx[i], totalStakedGmx);\n }\n\n Transfer[] memory transfer = FeeDistributorUtils.computeTransfers(feeAmountsGmx, target);\n\n uint256[] memory bridgingAmounts = _createUintArray(chainIdsLength);\n\n for (uint256 j; j < transfer.length; j++) {\n if (transfer[j].from == currentChainIndex) {\n bridgingAmounts[transfer[j].to] = transfer[j].amount;\n }\n }\n\n return _bridgeGmx(chainIds, bridgingAmounts);\n }\n\n function _bridgeGmx(uint256[] memory chainIds, uint256[] memory bridgingAmounts) internal returns (uint256) {\n // Execute bridging transactions from current chain\n OFTCore layerzeroOft = OFTCore(_getAddressInfo(LAYERZERO_OFT));\n uint256 decimalConversionRate = layerzeroOft.decimalConversionRate();\n uint256 totalGmxBridgedOut;\n for (uint256 i; i < chainIds.length; i++) {\n uint256 bridgingAmount = bridgingAmounts[i];\n if (bridgingAmount == 0) continue;\n\n uint256 sendAmount = _removeDust(bridgingAmount, decimalConversionRate);\n\n // Move GMX needed for bridging to this contract from FeeDistributorVault\n _transferOut(gmx, address(this), sendAmount);\n\n // If the Layerzero OFT contract on this chain requires GMX approval, approve the sendAmount\n if (layerzeroOft.approvalRequired()) {\n IERC20(gmx).approve(address(layerzeroOft), sendAmount);\n }\n\n // Prepare remaining params needed for the bridging transaction\n uint256 chainId = chainIds[i];\n uint32 layerzeroChainId = uint32(_getUint(Keys2.feeDistributorLayerZeroChainIdKey(chainId)));\n bytes32 to = Cast.toBytes32(_getAddressInfoForChain(chainId, Keys.FEE_RECEIVER));\n uint256 minAmountOut = _removeDust(\n Precision.applyFactor(sendAmount, _getUint(Keys2.feeDistributorBridgeSlippageFactorKey(chainId))),\n decimalConversionRate\n );\n SendParam memory sendParam = SendParam(\n layerzeroChainId,\n to,\n sendAmount,\n minAmountOut,\n EMPTY_BYTES,\n EMPTY_BYTES,\n EMPTY_BYTES\n );\n MessagingFee memory messagingFee = layerzeroOft.quoteSend(sendParam, false);\n\n // Make the bridge call to the OFT contract\n layerzeroOft.send{ value: messagingFee.nativeFee }(sendParam, messagingFee, address(feeDistributorVault));\n\n // Add to the total bridged out\n totalGmxBridgedOut += sendAmount;\n }\n\n return totalGmxBridgedOut;\n }\n\n function _calculateAndTransferWntCosts(\n uint256 wntReferralRewardsInUsd,\n uint256 feesV1Usd,\n uint256 feesV2Usd\n ) internal returns (uint256, uint256, uint256, uint256) {\n // the WNT fee amount related calculations\n uint256 totalWntBalance = _getFeeDistributorVaultBalance(wnt);\n\n // calculate the WNT that needs to be sent to each keeper\n (uint256 keeperCostsV1, uint256 keeperCostsV2) = FeeDistributorUtils.calculateKeeperCosts(dataStore);\n uint256 wntForKeepers = keeperCostsV1 + keeperCostsV2;\n\n // calculate the WNT for chainlink costs and amount of WNT to be sent to the treasury\n (uint256 wntForChainlink, uint256 wntForTreasury) = _calculateChainlinkAndTreasuryAmounts(\n totalWntBalance,\n feesV1Usd,\n feesV2Usd,\n keeperCostsV2\n );\n\n // validate wntReferralRewardsInUsd and calculate the referral rewards in WNT to be sent\n uint256 wntForReferralRewards = _calculateWntForReferralRewards(wntReferralRewardsInUsd, feesV1Usd);\n\n wntForTreasury = _finalizeWntForTreasury(\n totalWntBalance,\n keeperCostsV1,\n keeperCostsV2,\n wntForChainlink,\n wntForTreasury,\n wntForReferralRewards\n );\n\n _transferWntCosts(wntForKeepers, wntForChainlink, wntForTreasury);\n\n return (wntForKeepers, wntForChainlink, wntForTreasury, wntForReferralRewards);\n }\n\n function _finalizeWntForTreasury(\n uint256 totalWntBalance,\n uint256 keeperCostsV1,\n uint256 keeperCostsV2,\n uint256 wntForChainlink,\n uint256 wntForTreasury,\n uint256 wntForReferralRewards\n ) internal returns (uint256) {\n // calculate the remaining WNT for Treasury, validate the calculated amount and adjust if necessary\n uint256 wntBeforeV1KeeperCostsAndReferralRewards = totalWntBalance -\n keeperCostsV2 -\n wntForChainlink -\n wntForTreasury;\n\n uint256 keeperAndReferralCostsV1 = keeperCostsV1 + wntForReferralRewards;\n if (keeperAndReferralCostsV1 > wntBeforeV1KeeperCostsAndReferralRewards) {\n uint256 additionalWntForV1Costs = keeperAndReferralCostsV1 - wntBeforeV1KeeperCostsAndReferralRewards;\n if (additionalWntForV1Costs > wntForTreasury) {\n uint256 maxWntFromTreasury = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_WNT_AMOUNT_FROM_TREASURY);\n uint256 additionalWntFromTreasury = additionalWntForV1Costs - wntForTreasury;\n if (additionalWntFromTreasury > maxWntFromTreasury) {\n revert Errors.MaxWntFromTreasuryExceeded(maxWntFromTreasury, additionalWntFromTreasury);\n }\n IERC20(wnt).transferFrom(\n _getAddressInfo(TREASURY),\n address(feeDistributorVault),\n additionalWntFromTreasury\n );\n wntForTreasury = 0;\n } else {\n wntForTreasury -= additionalWntForV1Costs;\n }\n } else {\n uint256 remainingWntForTreasury = wntBeforeV1KeeperCostsAndReferralRewards - keeperAndReferralCostsV1;\n wntForTreasury += remainingWntForTreasury;\n }\n return wntForTreasury;\n }\n\n function _transferWntCosts(uint256 wntForKeepers, uint256 wntForChainlink, uint256 wntForTreasury) internal {\n // transfer the WNT that needs to be sent to each keeper\n address[] memory keepers = dataStore.getAddressArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n uint256[] memory keepersTargetBalance = dataStore.getUintArray(Keys2.FEE_DISTRIBUTOR_KEEPER_COSTS);\n uint256 wntToKeepers;\n for (uint256 i; i < keepers.length; i++) {\n address keeper = keepers[i];\n uint256 keeperBalance = keeper.balance;\n uint256 keeperTargetBalance = keepersTargetBalance[i];\n if (keeperBalance < keeperTargetBalance) {\n uint256 wntToKeeper = keeperTargetBalance - keeperBalance;\n feeDistributorVault.transferOutNativeToken(keeper, wntToKeeper);\n wntToKeepers += wntToKeeper;\n }\n }\n if (wntForKeepers != wntToKeepers) {\n revert Errors.KeeperAmountMismatch(wntForKeepers, wntToKeepers);\n }\n\n // transfer the WNT for chainlink costs and WNT for the treasury\n _transferOut(wnt, _getAddressInfo(CHAINLINK), wntForChainlink);\n _transferOut(wnt, _getAddressInfo(TREASURY), wntForTreasury);\n\n // transfer gmx fees for the week and update the last distribution time and tokens per interval\n address extendedGmxTracker = _getAddressInfoForChain(mockChainId, EXTENDED_GMX_TRACKER);\n uint256 feeAmountGmx = _getUint(Keys2.feeDistributorFeeAmountGmxKey(mockChainId));\n address distributor = IRewardTracker(extendedGmxTracker).distributor();\n _transferOut(gmx, extendedGmxTracker, feeAmountGmx);\n IRewardDistributor(distributor).updateLastDistributionTime();\n IRewardDistributor(distributor).setTokensPerInterval(feeAmountGmx / 1 weeks);\n }\n\n function _setUint(bytes32 fullKey, uint256 value) internal {\n dataStore.setUint(fullKey, value);\n }\n\n function _setDistributionState(uint256 value) internal {\n _setUint(Keys2.FEE_DISTRIBUTOR_STATE, value);\n }\n\n function _transferOut(address token, address receiver, uint256 amount) internal {\n feeDistributorVault.transferOut(token, receiver, amount);\n }\n\n function _emitFeeDistributionEvent(\n EventUtils.EventLogData memory eventData,\n string memory eventDescription\n ) internal {\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"eventDescription\", eventDescription);\n eventEmitter.emitEventLog(\"FeeDistributionEvent\", eventData);\n }\n\n function _setTokenPrices() internal {\n _setUint(Keys2.FEE_DISTRIBUTOR_GMX_PRICE, _getOraclePrice(gmxForOracle));\n _setUint(Keys2.FEE_DISTRIBUTOR_WNT_PRICE, _getOraclePrice(wnt));\n }\n\n function _calculateChainlinkAndTreasuryAmounts(\n uint256 totalWntBalance,\n uint256 feesV1Usd,\n uint256 feesV2Usd,\n uint256 keeperCostsV2\n ) internal view returns (uint256, uint256) {\n uint256 feesV1UsdInWnt = Precision.applyFactor(feesV1Usd, _getUint(Keys2.FEE_DISTRIBUTOR_V1_FEES_WNT_FACTOR));\n uint256 feesV2UsdInWnt = Precision.applyFactor(feesV2Usd, _getUint(Keys2.FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR));\n uint256 chainlinkTreasuryWntAmount = Precision.mulDiv(\n totalWntBalance,\n feesV2UsdInWnt,\n feesV1UsdInWnt + feesV2UsdInWnt\n );\n uint256 wntForChainlink = Precision.applyFactor(\n chainlinkTreasuryWntAmount,\n _getUint(Keys2.FEE_DISTRIBUTOR_CHAINLINK_FACTOR)\n );\n uint256 wntForTreasury = chainlinkTreasuryWntAmount - wntForChainlink - keeperCostsV2;\n\n return (wntForChainlink, wntForTreasury);\n }\n\n function _calculateWntForReferralRewards(\n uint256 wntReferralRewardsInUsd,\n uint256 feesV1Usd\n ) internal view returns (uint256) {\n uint256 maxWntReferralRewardsInUsdAmount = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_AMOUNT);\n if (wntReferralRewardsInUsd > maxWntReferralRewardsInUsdAmount) {\n revert Errors.MaxWntReferralRewardsInUsdAmountExceeded(\n wntReferralRewardsInUsd,\n maxWntReferralRewardsInUsdAmount\n );\n }\n\n uint256 maxWntReferralRewardsInUsdFactor = _getUint(Keys2.FEE_DISTRIBUTOR_MAX_REFERRAL_REWARDS_WNT_USD_FACTOR);\n uint256 maxWntReferralRewardsInUsd = Precision.applyFactor(feesV1Usd, maxWntReferralRewardsInUsdFactor);\n if (wntReferralRewardsInUsd > maxWntReferralRewardsInUsd) {\n revert Errors.MaxWntReferralRewardsInUsdExceeded(wntReferralRewardsInUsd, maxWntReferralRewardsInUsd);\n }\n\n uint256 scaledWntPrice = _getUint(Keys2.FEE_DISTRIBUTOR_WNT_PRICE) * Precision.FLOAT_PRECISION;\n uint256 wntForReferralRewards = Precision.toFactor(wntReferralRewardsInUsd, scaledWntPrice);\n\n return wntForReferralRewards;\n }\n\n function _getUint(bytes32 fullKey) internal view returns (uint256) {\n return dataStore.getUint(fullKey);\n }\n\n function _getAddress(bytes32 fullKey) internal view returns (address) {\n return dataStore.getAddress(fullKey);\n }\n\n function _getAddressInfo(bytes32 addressKey) internal view returns (address) {\n return _getAddress(Keys2.feeDistributorAddressInfoKey(addressKey));\n }\n\n function _getAddressInfoForChain(uint256 chainId, bytes32 addressKey) internal view returns (address) {\n return _getAddress(Keys2.feeDistributorAddressInfoForChainKey(chainId, addressKey));\n }\n\n function _getFeeDistributorVaultBalance(address token) internal view returns (uint256) {\n return IERC20(token).balanceOf(address(feeDistributorVault));\n }\n\n function _getOraclePrice(address token) internal view returns (uint256) {\n // ChainlinkPriceFeedProvider.getOraclePrice() is not used since the prices are for non-stablecoin tokens\n (bool hasPriceFeed, uint256 price) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStoreForOracle, token);\n\n if (!hasPriceFeed) {\n revert Errors.EmptyChainlinkPriceFeed(token);\n }\n\n return price;\n }\n\n function _validateReadResponseTimestamp(uint256 readResponseTimestamp) internal view {\n if (block.timestamp - readResponseTimestamp > _getUint(Keys2.FEE_DISTRIBUTOR_MAX_READ_RESPONSE_DELAY)) {\n revert Errors.OutdatedReadResponse(readResponseTimestamp);\n }\n }\n\n function _validateDistributionState(DistributionState allowedDistributionState) internal view {\n uint256 distributionStateUint = _getUint(Keys2.FEE_DISTRIBUTOR_STATE);\n if (allowedDistributionState != DistributionState(distributionStateUint)) {\n revert Errors.InvalidDistributionState(distributionStateUint);\n }\n }\n\n function _validateDistributionNotCompleted() internal view {\n uint256 dayOfWeek = ((block.timestamp / 1 days) + 4) % 7;\n uint256 daysSinceDistributionDay = (dayOfWeek + 7 - _getUint(Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_DAY)) % 7;\n uint256 midnightToday = block.timestamp - (block.timestamp % 1 days);\n uint256 startOfDistributionWeek = midnightToday - (daysSinceDistributionDay * 1 days);\n uint256 lastDistributionTime = _getUint(Keys2.FEE_DISTRIBUTOR_DISTRIBUTION_TIMESTAMP);\n if (lastDistributionTime > startOfDistributionWeek) {\n revert Errors.FeeDistributionAlreadyCompleted(lastDistributionTime, startOfDistributionWeek);\n }\n }\n\n function _setReadRequestInput(\n uint32 chainId,\n address target,\n bytes memory callData\n ) internal pure returns (MultichainReaderUtils.ReadRequestInputs memory) {\n return MultichainReaderUtils.ReadRequestInputs(chainId, target, callData);\n }\n\n function _createUintArray(uint256 arrayLength) internal pure returns (uint256[] memory) {\n return new uint256[](arrayLength);\n }\n\n function _createAddressArray(uint256 arrayLength) internal pure returns (address[] memory) {\n return new address[](arrayLength);\n }\n\n function _decodeReadData(\n bytes calldata readData,\n uint256 targetChainIndex\n ) internal pure returns (uint256, uint256) {\n uint256 offset = targetChainIndex * 96;\n (uint256 feeAmountGmx1, uint256 feeAmountGmx2, uint256 stakedGmx) = abi.decode(\n readData[offset:(offset + 96)],\n (uint256, uint256, uint256)\n );\n uint256 feeAmount = feeAmountGmx1 + feeAmountGmx2;\n return (feeAmount, stakedGmx);\n }\n\n function _removeDust(uint256 amount, uint256 decimalConversionRate) internal pure returns (uint256) {\n return (amount / decimalConversionRate) * decimalConversionRate;\n }\n\n function _setUintItem(\n EventUtils.EventLogData memory eventData,\n uint256 itemNumber,\n string memory itemName,\n uint256 uintItem\n ) internal pure {\n eventData.uintItems.setItem(itemNumber, itemName, uintItem);\n }\n}\n" + }, + "contracts/mock/MockGelatoRelay.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../exchange/IOrderHandler.sol\";\nimport \"../order/OrderVault.sol\";\nimport \"../router/Router.sol\";\nimport \"../router/relay/GelatoRelayRouter.sol\";\n\ncontract MockGelatoRelayRouter is GelatoRelayRouter {\n struct Nested {\n uint256 foo;\n bool bar;\n }\n\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n IOrderHandler _orderHandler,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IExternalHandler _externalHandler\n ) GelatoRelayRouter(_router, _roleStore, _dataStore, _eventEmitter, _oracle, _orderHandler, _orderVault, _swapHandler, _externalHandler) {}\n\n function testCancelOrderSignature(\n IRelayUtils.RelayParams calldata relayParams,\n bytes32 key,\n address account,\n uint256 chainId\n ) external view {\n bytes32 structHash = RelayUtils.getCancelOrderStructHash(relayParams, key);\n _handleSignature(structHash, relayParams.signature, account, chainId);\n }\n\n function testSimpleSignature(address account, bytes calldata signature, uint256 chainId) external view {\n bytes32 structHash = keccak256(abi.encode(keccak256(bytes(\"PrimaryStruct(address account)\")), account));\n _handleSignature(structHash, signature, account, chainId);\n }\n\n function testNestedSignature(\n Nested memory nested,\n address account,\n bytes calldata signature,\n uint256 chainId\n ) external view {\n bytes32 nestedStructHash = keccak256(\n abi.encode(keccak256(bytes(\"Nested(uint256 foo,bool bar)\")), nested.foo, nested.bar)\n );\n bytes32 structHash = keccak256(\n abi.encode(\n keccak256(bytes(\"PrimaryStruct(address account,Nested nested)Nested(uint256 foo,bool bar)\")),\n account,\n nestedStructHash\n )\n );\n _handleSignature(structHash, signature, account, chainId);\n }\n\n function testArraySignature(\n address[] memory array,\n address account,\n bytes calldata signature,\n uint256 chainId\n ) external view {\n bytes32 structHash = keccak256(\n abi.encode(\n keccak256(bytes(\"PrimaryStruct(address account,address[] array)\")),\n account,\n keccak256(abi.encodePacked(array))\n )\n );\n _handleSignature(structHash, signature, account, chainId);\n }\n\n function _handleSignature(\n bytes32 structHash,\n bytes calldata signature,\n address account,\n uint256 chainId\n ) internal view {\n bytes32 domainSeparator = RelayUtils.getDomainSeparator(chainId);\n bytes32 digest = ECDSA.toTypedDataHash(domainSeparator, structHash);\n\n RelayUtils.validateSignature(\n domainSeparator,\n digest,\n signature,\n account,\n \"call\"\n );\n }\n}\n" + }, + "contracts/mock/MockMultichainReaderOriginator.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../multichain/MultichainReader.sol\";\n\ncontract MockMultichainReaderOriginator {\n mapping(bytes32 guid => MultichainReaderUtils.ReceivedData) public receivedData;\n\n MultichainReaderUtils.ReceivedData public latestReceivedData =\n MultichainReaderUtils.ReceivedData(0, abi.encode(\"Nothing received yet.\"));\n\n bytes32 public latestGuid;\n\n MultichainReader public multichainReader;\n\n constructor(MultichainReader _multichainReader) {\n multichainReader = _multichainReader;\n }\n\n receive() external payable {}\n\n function processLzReceive(bytes32 guid, MultichainReaderUtils.ReceivedData memory receivedDataParam) external {\n receivedData[guid] = receivedDataParam;\n latestGuid = guid;\n latestReceivedData = receivedDataParam;\n }\n\n function setmultichainReader(MultichainReader _multichainReader) external {\n multichainReader = _multichainReader;\n }\n\n function callSendReadRequests(\n MultichainReaderUtils.ReadRequestInputs[] calldata readRequestInputs,\n MultichainReaderUtils.ExtraOptionsInputs calldata extraOptionsInputs\n ) external payable returns (MessagingReceipt memory) {\n MessagingFee memory messagingFee = multichainReader.quoteReadFee(readRequestInputs, extraOptionsInputs);\n MessagingReceipt memory messagingReceipt = multichainReader.sendReadRequests{ value: messagingFee.nativeFee }(\n readRequestInputs,\n extraOptionsInputs\n );\n return (messagingReceipt);\n }\n\n function callQuoteReadFee(\n MultichainReaderUtils.ReadRequestInputs[] calldata readRequestInputs,\n MultichainReaderUtils.ExtraOptionsInputs calldata extraOptionsInputs\n ) external view returns (uint256) {\n MessagingFee memory messagingFee = multichainReader.quoteReadFee(readRequestInputs, extraOptionsInputs);\n return (messagingFee.nativeFee);\n }\n\n function testRead() external pure returns (uint256) {\n return 12345;\n }\n}\n" + }, + "contracts/mock/MockOracleProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../contracts/oracle/OracleUtils.sol\";\nimport \"../../contracts/oracle/IOracleProvider.sol\";\n\ncontract MockOracleProvider is IOracleProvider {\n function getOraclePrice(\n address token,\n bytes memory /* data */\n ) external view override returns (OracleUtils.ValidatedPrice memory) {\n // Return a dummy price for testing\n return OracleUtils.ValidatedPrice({\n token: token,\n min: 1000,\n max: 1000,\n timestamp: block.timestamp,\n provider: address(this)\n });\n }\n\n function shouldAdjustTimestamp() external pure returns (bool) {\n return true;\n }\n\n function isChainlinkOnChainProvider() external pure returns (bool) {\n return false;\n }\n}\n" + }, + "contracts/mock/MockStargatePool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { MessagingFee, OFTReceipt, SendParam, MessagingReceipt, OFTLimit, OFTFeeDetail } from \"@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol\";\nimport { OFTComposeMsgCodec } from \"@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol\";\n\nimport {LayerZeroProvider} from \"../multichain/LayerZeroProvider.sol\";\n\ncontract MockStargatePool {\n using SafeERC20 for IERC20;\n\n address public token;\n uint256 public constant BRIDGE_OUT_FEE = 0.001 ether;\n uint32 public constant SRC_EID = 1; // Mock endpoint id for source chain\n\n constructor(address _token) {\n token = _token;\n }\n\n /**\n * @dev Mock function to simulate receiving tokens from source chain and delivering to target chain (bridgeIn flow)\n * @param layerZeroProvider The recipient contract (LayerZeroProvider)\n * @param _amount The amount of tokens to send\n * @param _message The encoded message containing account, token, srcChainId\n */\n function sendToken(LayerZeroProvider layerZeroProvider, uint256 _amount, bytes calldata _message) external payable {\n // prepend composeFrom (msg.sender) to the user payload\n bytes memory encodedMsg = abi.encodePacked(\n OFTComposeMsgCodec.addressToBytes32(msg.sender),\n _message\n );\n\n bytes memory composedMsg = OFTComposeMsgCodec.encode(\n uint64(block.timestamp), // mock nonce\n SRC_EID,\n _amount,\n encodedMsg\n );\n\n if (token == address(0)) {\n require(msg.value == _amount, \"Incorrect ETH amount sent\");\n } else {\n IERC20(token).transferFrom(msg.sender, address(layerZeroProvider), _amount);\n }\n\n // Simulate cross-chain message delivery by directly calling lzCompose on the LayerZeroProvider contract\n layerZeroProvider.lzCompose{value: msg.value}(\n address(this),\n bytes32(uint256(1)), // mock guid\n composedMsg,\n address(this),\n \"\" // extraData\n );\n }\n\n /**\n * @dev Mock send function that handles the cross-chain transfer (bridgeOut flow)\n */\n function send(\n SendParam memory _sendParam,\n MessagingFee memory,\n address // _refundReceiver\n ) external payable returns (MessagingReceipt memory, OFTReceipt memory) {\n address receiver = address(uint160(uint256(_sendParam.to)));\n IERC20(token).transferFrom(msg.sender, receiver, _sendParam.amountLD);\n\n MessagingReceipt memory msgReceipt = MessagingReceipt({\n guid: bytes32(uint256(block.timestamp)),\n nonce: uint64(1),\n fee: MessagingFee({ nativeFee: msg.value, lzTokenFee: 0 })\n });\n\n OFTReceipt memory oftReceipt = OFTReceipt({\n amountSentLD: _sendParam.amountLD,\n amountReceivedLD: _sendParam.amountLD\n });\n\n return (msgReceipt, oftReceipt);\n }\n\n function quoteOFT(\n SendParam calldata _sendParam\n )\n external\n pure\n returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)\n {\n oftLimit = OFTLimit({ minAmountLD: 0, maxAmountLD: type(uint256).max });\n\n oftFeeDetails = new OFTFeeDetail[](1);\n oftFeeDetails[0] = OFTFeeDetail({ feeAmountLD: 0, description: \"No fees\" });\n\n oftReceipt = OFTReceipt({\n amountSentLD: _sendParam.amountLD,\n amountReceivedLD: _sendParam.amountLD // Assume no fees on receiving side\n });\n\n return (oftLimit, oftFeeDetails, oftReceipt);\n }\n\n function quoteSend(SendParam memory, bool) external pure returns (MessagingFee memory msgFee) {\n return MessagingFee({ nativeFee: BRIDGE_OUT_FEE, lzTokenFee: 0 });\n }\n\n receive() external payable {}\n}\n" + }, + "contracts/mock/MockStargatePoolNative.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./MockStargatePool.sol\";\n\ncontract MockStargatePoolNative is MockStargatePool {\n constructor() MockStargatePool(address(0)) {}\n}\n" + }, + "contracts/mock/MockStargatePoolUsdc.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./MockStargatePool.sol\";\n\ncontract MockStargatePoolUsdc is MockStargatePool {\n constructor(address _usdc) MockStargatePool(_usdc) {}\n\n // Allow token address to be changed to support GM / GLV tokens\n function updateToken(address _token) external {\n require(_token != address(0), \"Invalid token address\");\n token = _token;\n }\n}\n" + }, + "contracts/mock/Multicall3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Multicall3\n/// @notice Aggregate results from multiple function calls\n/// @dev Multicall & Multicall2 backwards-compatible\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n/// @author Andreas Bigger \n/// @author Matt Solomon \ncontract Multicall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n /// @notice Backwards-compatible call aggregation with Multicall\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return returnData An array of bytes containing the responses\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = block.number;\n uint256 length = calls.length;\n returnData = new bytes[](length);\n Call calldata call;\n for (uint256 i; i < length;) {\n bool success;\n call = calls[i];\n (success, returnData[i]) = call.target.call(call.callData);\n require(success, \"Multicall3: call failed\");\n unchecked { ++i; }\n }\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls without requiring success\n /// @param requireSuccess If true, require all calls to succeed\n /// @param calls An array of Call structs\n /// @return returnData An array of Result structs\n function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call calldata call;\n for (uint256 i; i < length;) {\n Result memory result = returnData[i];\n call = calls[i];\n (result.success, result.returnData) = call.target.call(call.callData);\n if (requireSuccess) require(result.success, \"Multicall3: call failed\");\n unchecked { ++i; }\n }\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls and allow failures using tryAggregate\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return blockHash The hash of the block where the calls were executed\n /// @return returnData An array of Result structs\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls and allow failures using tryAggregate\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return blockHash The hash of the block where the calls were executed\n /// @return returnData An array of Result structs\n function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n\n /// @notice Aggregate calls, ensuring each returns success if required\n /// @param calls An array of Call3 structs\n /// @return returnData An array of Result structs\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call3 calldata calli;\n for (uint256 i; i < length;) {\n Result memory result = returnData[i];\n calli = calls[i];\n (result.success, result.returnData) = calli.target.call(calli.callData);\n assembly {\n // Revert if the call fails and failure is not allowed\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\n // set \"Error(string)\" signature: bytes32(bytes4(keccak256(\"Error(string)\")))\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n // set data offset\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\n // set length of revert string\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\n // set revert string: bytes32(abi.encodePacked(\"Multicall3: call failed\"))\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\n revert(0x00, 0x64)\n }\n }\n unchecked { ++i; }\n }\n }\n\n /// @notice Aggregate calls with a msg value\n /// @notice Reverts if msg.value is less than the sum of the call values\n /// @param calls An array of Call3Value structs\n /// @return returnData An array of Result structs\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\n uint256 valAccumulator;\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call3Value calldata calli;\n for (uint256 i; i < length;) {\n Result memory result = returnData[i];\n calli = calls[i];\n uint256 val = calli.value;\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\n unchecked { valAccumulator += val; }\n (result.success, result.returnData) = calli.target.call{value: val}(calli.callData);\n assembly {\n // Revert if the call fails and failure is not allowed\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\n // set \"Error(string)\" signature: bytes32(bytes4(keccak256(\"Error(string)\")))\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n // set data offset\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\n // set length of revert string\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\n // set revert string: bytes32(abi.encodePacked(\"Multicall3: call failed\"))\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\n revert(0x00, 0x84)\n }\n }\n unchecked { ++i; }\n }\n // Finally, make sure the msg.value = SUM(call[0...i].value)\n require(msg.value == valAccumulator, \"Multicall3: value mismatch\");\n }\n\n /// @notice Returns the block hash for the given block number\n /// @param blockNumber The block number\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n\n /// @notice Returns the block number\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n\n /// @notice Returns the block coinbase\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n\n /// @notice Returns the block gas limit\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n\n /// @notice Returns the block timestamp\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n\n /// @notice Returns the (ETH) balance of a given address\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n\n /// @notice Returns the block hash of the last block\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n unchecked {\n blockHash = blockhash(block.number - 1);\n }\n }\n\n /// @notice Gets the base fee of the given block\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\n function getBasefee() public view returns (uint256 basefee) {\n basefee = block.basefee;\n }\n\n /// @notice Returns the chain id\n function getChainId() public view returns (uint256 chainid) {\n chainid = block.chainid;\n }\n}\n" + }, + "contracts/mock/ReferralStorage.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../referral/IReferralStorage.sol\";\nimport \"./Governable.sol\";\nimport \"../referral/ReferralTier.sol\";\n\n// @title ReferralStorage\n// @dev Mock referral storage for testing and testnets\ncontract ReferralStorage is IReferralStorage, Governable {\n uint256 public constant BASIS_POINTS = 10000;\n\n // @dev mapping of affiliate to discount share for trader\n // this overrides the default value in the affiliate's tier\n mapping (address => uint256) public override referrerDiscountShares;\n // @dev mapping of affiliate to tier\n mapping (address => uint256) public override referrerTiers;\n // @dev mapping tier level to tier values\n mapping (uint256 => ReferralTier.Props) public override tiers;\n\n // @dev handlers for access control\n mapping (address => bool) public isHandler;\n\n // @dev mapping of referral code to affiliate\n mapping (bytes32 => address) public override codeOwners;\n // @dev mapping of trader to referral code\n mapping (address => bytes32) public override traderReferralCodes;\n\n // @param handler the handler being set\n // @param isActive whether the handler is being set to active or inactive\n event SetHandler(address handler, bool isActive);\n // @param account address of the trader\n // @param code the referral code\n event SetTraderReferralCode(address account, bytes32 code);\n // @param tierId the tier level\n // @param totalRebate the total rebate for the tier (affiliate reward + trader discount)\n // @param discountShare the share of the totalRebate for traders\n event SetTier(uint256 tierId, uint256 totalRebate, uint256 discountShare);\n // @param referrer the affiliate\n // @param tierId the new tier level\n event SetReferrerTier(address referrer, uint256 tierId);\n // @param referrer the affiliate\n // @param discountShare the share of the totalRebate for traders\n event SetReferrerDiscountShare(address referrer, uint256 discountShare);\n // @param account the address of the affiliate\n // @param code the referral code\n event RegisterCode(address account, bytes32 code);\n // @param account the previous owner of the referral code\n // @param newAccount the new owner of the referral code\n // @param code the referral code\n event SetCodeOwner(address account, address newAccount, bytes32 code);\n // @param newAccount the new owner of the referral code\n // @param code the referral code\n event GovSetCodeOwner(bytes32 code, address newAccount);\n\n modifier onlyHandler() {\n require(isHandler[msg.sender], \"ReferralStorage: forbidden\");\n _;\n }\n\n // @dev set an address as a handler\n // @param _handler address of the handler\n // @param _isActive whether to set the handler as active or inactive\n function setHandler(address _handler, bool _isActive) external onlyGov {\n isHandler[_handler] = _isActive;\n emit SetHandler(_handler, _isActive);\n }\n\n // @dev set values for a tier\n // @param _tierId the ID of the tier to set\n // @param _totalRebate the total rebate\n // @param _discountShare the discount share\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external override onlyGov {\n require(_totalRebate <= BASIS_POINTS, \"ReferralStorage: invalid totalRebate\");\n require(_discountShare <= BASIS_POINTS, \"ReferralStorage: invalid discountShare\");\n\n ReferralTier.Props memory tier = tiers[_tierId];\n tier.totalRebate = _totalRebate;\n tier.discountShare = _discountShare;\n tiers[_tierId] = tier;\n emit SetTier(_tierId, _totalRebate, _discountShare);\n }\n\n // @dev set the tier for an affiliate\n // @param _referrer the address of the affiliate\n // @param _tierId the tier to set to\n function setReferrerTier(address _referrer, uint256 _tierId) external override onlyGov {\n referrerTiers[_referrer] = _tierId;\n emit SetReferrerTier(_referrer, _tierId);\n }\n\n // @dev set the discount share for an affiliate\n // @param _discountShare the discount share to set to\n function setReferrerDiscountShare(uint256 _discountShare) external {\n require(_discountShare <= BASIS_POINTS, \"ReferralStorage: invalid discountShare\");\n\n referrerDiscountShares[msg.sender] = _discountShare;\n emit SetReferrerDiscountShare(msg.sender, _discountShare);\n }\n\n // @dev set the referral code for a trader\n // @param _account the address of the trader\n // @param _code the referral code to set to\n function setTraderReferralCode(address _account, bytes32 _code) external override onlyHandler {\n _setTraderReferralCode(_account, _code);\n }\n\n // @dev set the referral code for a trader\n // @param _code the referral code to set to\n function setTraderReferralCodeByUser(bytes32 _code) external {\n _setTraderReferralCode(msg.sender, _code);\n }\n\n // @dev register a referral code\n // @param _code the referral code to register\n function registerCode(bytes32 _code) external {\n require(_code != bytes32(0), \"ReferralStorage: invalid _code\");\n require(codeOwners[_code] == address(0), \"ReferralStorage: code already exists\");\n\n codeOwners[_code] = msg.sender;\n emit RegisterCode(msg.sender, _code);\n }\n\n // @dev for affiliates to set a new owner for a referral code they own\n // @param _code the referral code\n // @param _newAccount the new owner\n function setCodeOwner(bytes32 _code, address _newAccount) external {\n require(_code != bytes32(0), \"ReferralStorage: invalid _code\");\n\n address account = codeOwners[_code];\n require(msg.sender == account, \"ReferralStorage: forbidden\");\n\n codeOwners[_code] = _newAccount;\n emit SetCodeOwner(msg.sender, _newAccount, _code);\n }\n\n // @dev set the owner of a referral code\n // @param _code the referral code\n // @param _newAccount the new owner\n function govSetCodeOwner(bytes32 _code, address _newAccount) external override onlyGov {\n require(_code != bytes32(0), \"ReferralStorage: invalid _code\");\n\n codeOwners[_code] = _newAccount;\n emit GovSetCodeOwner(_code, _newAccount);\n }\n\n // @dev get the referral info for a trader\n // @param _account the address of the trader\n function getTraderReferralInfo(address _account) external override view returns (bytes32, address) {\n bytes32 code = traderReferralCodes[_account];\n address referrer;\n if (code != bytes32(0)) {\n referrer = codeOwners[code];\n }\n return (code, referrer);\n }\n\n // @dev set the referral code for a trader\n // @param _account the address of the trader\n // @param _code the referral code\n function _setTraderReferralCode(address _account, bytes32 _code) private {\n traderReferralCodes[_account] = _code;\n emit SetTraderReferralCode(_account, _code);\n }\n}\n" + }, + "contracts/mock/RevertingCallbackReceiver.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../callback/IDepositCallbackReceiver.sol\";\n\ncontract RevertingCallbackReceiver is IDepositCallbackReceiver {\n function afterDepositExecution(bytes32 /* key */, EventUtils.EventLogData memory /* deposit */, EventUtils.EventLogData memory /* eventData */) external pure {\n revert(\"error\");\n }\n\n function afterDepositCancellation(bytes32 /* key */, EventUtils.EventLogData memory /* deposit */, EventUtils.EventLogData memory /* eventData */) external pure {\n revert(\"error\");\n }\n}\n" + }, + "contracts/multichain/BridgeOutFromControllerUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../error/ErrorUtils.sol\";\nimport \"../utils/Array.sol\";\n\nimport \"./IMultichainProvider.sol\";\nimport \"./IMultichainTransferRouter.sol\";\nimport \"./MultichainEventUtils.sol\";\n\n// @title BridgeOutFromControllerUtils\nlibrary BridgeOutFromControllerUtils {\n struct BridgeOutFromControllerParams {\n address account;\n address receiver;\n uint256 srcChainId;\n address token;\n uint256 amount;\n address secondaryToken;\n uint256 secondaryAmount;\n bytes32[] dataList;\n }\n\n struct _BridgeOutParams {\n IMultichainProvider.ActionType actionType;\n address account;\n address token;\n uint256 srcChainId;\n uint256 desChainId;\n uint256 amount;\n uint256 minAmountOut;\n uint256 deadline;\n address provider;\n bytes providerData;\n }\n\n struct BridgeOutActionData {\n uint256 desChainId;\n uint256 deadline;\n address provider;\n bytes providerData;\n uint256 minAmountOut;\n address secondaryProvider;\n bytes secondaryProviderData;\n uint256 secondaryMinAmountOut;\n }\n\n /// @dev abi.decode can fail if dataList is not properly formed, which would cause the deposit to be cancelled\n /// @dev first item of dataList should be the GMX_DATA_ACTION hash if dataList is intended to be used for bridging out tokens\n // note that if account != receiver the transfer will just be skipped instead of throwing an error\n function bridgeOutFromController(\n EventEmitter eventEmitter,\n IMultichainTransferRouter multichainTransferRouter,\n address account,\n address receiver,\n uint256 srcChainId,\n address token,\n uint256 amount,\n bytes32[] memory dataList\n ) external {\n if (!_shouldProcessBridgeOut(\n account,\n receiver,\n amount,\n srcChainId,\n dataList\n )) {\n return;\n }\n\n bytes memory data = Array.dataArrayToBytes(dataList);\n _BridgeOutParams memory _bridgeOutParams;\n bytes memory actionData;\n (_bridgeOutParams.actionType, actionData) = abi.decode(\n data,\n (IMultichainProvider.ActionType, bytes)\n );\n\n if (_bridgeOutParams.actionType == IMultichainProvider.ActionType.BridgeOut) {\n (_bridgeOutParams.desChainId, _bridgeOutParams.deadline, _bridgeOutParams.provider, _bridgeOutParams.providerData, _bridgeOutParams.minAmountOut) = abi.decode(\n actionData,\n (uint256, uint256, address, bytes, uint256)\n );\n\n _bridgeOutParams.account = account;\n _bridgeOutParams.srcChainId = srcChainId;\n _bridgeOutParams.token = token;\n _bridgeOutParams.amount = amount;\n\n _bridgeOut(\n eventEmitter,\n multichainTransferRouter,\n _bridgeOutParams\n );\n }\n }\n\n function bridgeOutFromController(\n EventEmitter eventEmitter,\n IMultichainTransferRouter multichainTransferRouter,\n BridgeOutFromControllerParams memory params\n ) external {\n if (!_shouldProcessBridgeOut(\n params.account,\n params.receiver,\n params.amount + params.secondaryAmount,\n params.srcChainId,\n params.dataList\n )) {\n return;\n }\n\n bytes memory data = Array.dataArrayToBytes(params.dataList);\n _BridgeOutParams memory _bridgeOutParams;\n\n bytes memory actionData;\n (_bridgeOutParams.actionType, actionData) = abi.decode(\n data,\n (IMultichainProvider.ActionType, bytes)\n );\n\n if (_bridgeOutParams.actionType == IMultichainProvider.ActionType.BridgeOut) {\n if (params.token == params.secondaryToken || params.secondaryToken == address(0)) {\n // providerData is to contain information such as dstEid\n (\n _bridgeOutParams.desChainId,\n _bridgeOutParams.deadline,\n _bridgeOutParams.provider,\n _bridgeOutParams.providerData,\n _bridgeOutParams.minAmountOut\n ) = abi.decode(\n actionData,\n (uint256, uint256, address, bytes, uint256)\n );\n\n _bridgeOutParams.account = params.account;\n _bridgeOutParams.srcChainId = params.srcChainId;\n _bridgeOutParams.token = params.token;\n _bridgeOutParams.amount = params.amount + params.secondaryAmount;\n\n _bridgeOut(\n eventEmitter,\n multichainTransferRouter,\n _bridgeOutParams\n );\n } else {\n BridgeOutActionData memory decodedActionData = abi.decode(actionData, (BridgeOutActionData));\n\n _bridgeOut(\n eventEmitter,\n multichainTransferRouter,\n _BridgeOutParams({\n actionType: _bridgeOutParams.actionType,\n account: params.account,\n token: params.token,\n srcChainId: params.srcChainId,\n desChainId: decodedActionData.desChainId,\n amount: params.amount,\n minAmountOut: decodedActionData.minAmountOut,\n deadline: decodedActionData.deadline,\n provider: decodedActionData.provider,\n providerData: decodedActionData.providerData\n })\n );\n\n _bridgeOut(\n eventEmitter,\n multichainTransferRouter,\n _BridgeOutParams({\n actionType: _bridgeOutParams.actionType,\n account: params.account,\n token: params.secondaryToken,\n srcChainId: params.srcChainId,\n desChainId: decodedActionData.desChainId,\n amount: params.secondaryAmount,\n minAmountOut: decodedActionData.secondaryMinAmountOut,\n deadline: decodedActionData.deadline,\n provider: decodedActionData.secondaryProvider,\n providerData: decodedActionData.secondaryProviderData\n })\n );\n }\n }\n }\n\n function _bridgeOut(\n EventEmitter eventEmitter,\n IMultichainTransferRouter multichainTransferRouter,\n _BridgeOutParams memory params\n ) internal {\n if (params.amount == 0) {\n return;\n }\n\n IRelayUtils.BridgeOutParams memory bridgeOutParams = IRelayUtils.BridgeOutParams({\n token: params.token,\n amount: params.amount,\n minAmountOut: params.minAmountOut,\n provider: params.provider,\n data: params.providerData\n });\n\n try multichainTransferRouter.bridgeOutFromController(params.account, params.srcChainId, params.desChainId, params.deadline, bridgeOutParams) {\n MultichainEventUtils.emitMultichainBridgeAction(eventEmitter, address(this), params.account, params.srcChainId, uint256(params.actionType));\n } catch Error(string memory reason) {\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), params.account, params.srcChainId, uint256(params.actionType), reason);\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), params.account, params.srcChainId, uint256(params.actionType), reason);\n }\n }\n\n function _shouldProcessBridgeOut(\n address account,\n address receiver,\n uint256 amount,\n uint256 srcChainId,\n bytes32[] memory dataList\n ) internal pure returns (bool) {\n if (account != receiver) {\n // bridging out from a recipient address is not allowed (GM / GLV tokens are minted directly to the recipient)\n // ensuring the bridging fee is paid by the account, otherwise an attacker could consume\n // any account's wnt balance as bridging fee by donating a minimal amount of gm or glv\n return false;\n }\n if (amount == 0) {\n return false;\n }\n if (srcChainId == 0) {\n return false;\n }\n if (dataList.length == 0 || dataList[0] != Keys.GMX_DATA_ACTION) {\n return false;\n }\n\n return true;\n }\n}\n" + }, + "contracts/multichain/IMultichainGlvRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/relay/IRelayUtils.sol\";\nimport \"../glv/glvDeposit/IGlvDepositUtils.sol\";\nimport \"../glv/glvWithdrawal/IGlvWithdrawalUtils.sol\";\n\ninterface IMultichainGlvRouter {\n function createGlvDeposit(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvDepositUtils.CreateGlvDepositParams memory params\n ) external returns (bytes32);\n\n function createGlvWithdrawal(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams memory params\n ) external returns (bytes32);\n}\n" + }, + "contracts/multichain/IMultichainGmRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/relay/IRelayUtils.sol\";\nimport \"../deposit/IDepositUtils.sol\";\nimport \"../withdrawal/IWithdrawalUtils.sol\";\nimport \"../shift/IShiftUtils.sol\";\n\ninterface IMultichainGmRouter {\n function createDeposit(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IDepositUtils.CreateDepositParams calldata params\n ) external returns (bytes32);\n\n function createWithdrawal(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IWithdrawalUtils.CreateWithdrawalParams calldata params\n ) external returns (bytes32);\n\n function createShift(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IShiftUtils.CreateShiftParams calldata params\n ) external returns (bytes32);\n}\n" + }, + "contracts/multichain/IMultichainOrderRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/relay/IRelayUtils.sol\";\n\ninterface IMultichainOrderRouter {\n function batch(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.BatchParams calldata params\n ) external returns (bytes32[] memory);\n\n function createOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external returns (bytes32);\n\n function updateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.UpdateOrderParams calldata params\n ) external;\n\n function cancelOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bytes32 key\n ) external;\n\n function setTraderReferralCode(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bytes32 referralCode\n ) external;\n}\n" + }, + "contracts/multichain/IMultichainProvider.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/relay/IRelayUtils.sol\";\n\n/**\n * @title IMultichainProvider\n */\ninterface IMultichainProvider {\n enum ActionType {\n None,\n Deposit,\n GlvDeposit,\n BridgeOut,\n SetTraderReferralCode,\n Withdrawal,\n GlvWithdrawal\n }\n\n function bridgeOut(address account, uint256 srcChainId, IRelayUtils.BridgeOutParams memory params) external returns (uint256);\n\n function withdrawTokens(address token, address receiver, uint256 amount) external;\n}\n" + }, + "contracts/multichain/IMultichainTransferRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/relay/IRelayUtils.sol\";\n\ninterface IMultichainTransferRouter {\n function bridgeIn(address account, address token) external payable;\n\n function bridgeOut(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.BridgeOutParams calldata params\n ) external;\n\n function bridgeOutFromController(\n address account,\n uint256 srcChainId,\n uint256 desChainId,\n uint256 deadline,\n IRelayUtils.BridgeOutParams calldata params\n ) external;\n\n function transferOut(\n IRelayUtils.BridgeOutParams calldata params\n ) external;\n}\n" + }, + "contracts/multichain/IOriginator.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {MultichainReaderUtils} from \"./MultichainReaderUtils.sol\";\n\ninterface IOriginator {\n function processLzReceive(bytes32 guid, MultichainReaderUtils.ReceivedData calldata receivedDataInput) external;\n}\n" + }, + "contracts/multichain/LayerZeroProvider.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { ILayerZeroComposer } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol\";\nimport { MessagingFee, OFTReceipt, SendParam, MessagingReceipt } from \"@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol\";\nimport { OFTComposeMsgCodec } from \"@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol\";\n\nimport { IStargate } from \"@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol\";\n\nimport \"../event/EventEmitter.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../utils/Cast.sol\";\nimport \"../gas/GasUtils.sol\";\nimport \"../deposit/DepositStoreUtils.sol\";\nimport \"../glv/GlvUtils.sol\";\n\nimport \"./IMultichainProvider.sol\";\nimport \"./IMultichainGmRouter.sol\";\nimport \"./IMultichainGlvRouter.sol\";\nimport \"./IMultichainOrderRouter.sol\";\n\nimport \"./MultichainVault.sol\";\nimport \"./MultichainUtils.sol\";\n\n\n/**\n * @title LayerZeroProvider\n * Bridging In is done throught lzCompose (receives tokens + encoded message from a source chain)\n * Bridging Out is done through bridgeOut (sends tokens to a source chain)\n * Defines lzCompose function which:\n * - is called by the Stargate executor after tokens are delivered to this contract\n * - forwards the received tokens to MultichainVault and increases user's multichain balance\n * Defines bridgeOut function which:\n * - sends tokens to the Stargate executor for bridging out to the source chain\n */\ncontract LayerZeroProvider is IMultichainProvider, ILayerZeroComposer, RoleModule {\n struct BridgeOutCache {\n uint32 dstEid;\n uint256 valueToSend;\n MessagingReceipt msgReceipt;\n SendParam sendParam;\n MessagingFee messagingFee;\n OFTReceipt receipt;\n }\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n MultichainVault public immutable multichainVault;\n IMultichainGmRouter public immutable multichainGmRouter;\n IMultichainGlvRouter public immutable multichainGlvRouter;\n IMultichainOrderRouter public immutable multichainOrderRouter;\n\n constructor(\n DataStore _dataStore,\n RoleStore _roleStore,\n EventEmitter _eventEmitter,\n MultichainVault _multichainVault,\n IMultichainGmRouter _multichainGmRouter,\n IMultichainGlvRouter _multichainGlvRouter,\n IMultichainOrderRouter _multichainOrderRouter\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n multichainVault = _multichainVault;\n multichainGmRouter = _multichainGmRouter;\n multichainGlvRouter = _multichainGlvRouter;\n multichainOrderRouter = _multichainOrderRouter;\n }\n\n /**\n * @notice Called by Stargate after tokens have been delivered to this contract.\n * @dev Handles the receipt of bridged tokens and optionally executes a deposit action.\n *\n * @dev If a user bridges tokens with deposit data, and already has sufficient funds in their multichain balance,\n * it is possible for multiple bridge transactions to result in multiple deposits (i.e. double mints).\n * For example, if a user bridges 10 WETH and 20,000 USDC, both with deposit data, and already has enough funds,\n * both bridge transactions could result in a deposit.\n *\n * @dev It is recommended that the interface or frontend enforces that users only bridge amounts that would not\n * result in double deposits.\n *\n * @param from The address of the sender (i.e. Stargate address, not user's address).\n * param guid A global unique identifier for tracking the packet.\n * @param message Encoded message. Contains the params needed to record the deposit (account, srcChainId)\n * param executor The address of the Executor.\n * param extraData Any extra data or options to trigger on receipt.\n */\n function lzCompose(\n address from,\n bytes32 /*guid*/,\n bytes calldata message,\n address /*executor*/,\n bytes calldata /*extraData*/\n ) external payable {\n MultichainUtils.validateMultichainProvider(dataStore, from);\n MultichainUtils.validateMultichainEndpoint(dataStore, msg.sender);\n\n /// @dev The `account` field is user-supplied and not validated; any address may be provided by the sender\n // msg.sender and `from` need to be validated for `amountLD` and `token` to not be spoofable\n // additionally, the lzReceive, _credit and _debit functions of the OFT should be checked for any overrides\n // before the `amountLD` and `token` values can be trusted\n (address account, uint256 srcChainId, uint256 amountLD, bytes memory data) = _decodeLzComposeMsg(message);\n\n address token = IStargate(from).token();\n if (token == address(0x0)) {\n // `from` is StargatePoolNative\n TokenUtils.depositAndSendWrappedNativeToken(dataStore, address(multichainVault), amountLD);\n\n // if token is ETH then we need to use WNT\n token = TokenUtils.wnt(dataStore);\n } else {\n // `from` is e.g. StargatePoolUSDC\n TokenUtils.transfer(dataStore, token, address(multichainVault), amountLD);\n }\n MultichainUtils.recordBridgeIn(\n dataStore,\n eventEmitter,\n multichainVault,\n this,\n token,\n account,\n srcChainId\n );\n\n // note that for these functions, the remaining gas must be sufficient\n // otherwise the function will revert\n // if the action cannot be completed due to gas issues, the user would\n // need to manually call the function with the right amount of gas\n // srcChainId could be zero when returned from _decodeLzComposeMsg, skip follow up actions in this case\n if (srcChainId != 0 && data.length != 0) {\n (ActionType actionType, bytes memory actionData) = abi.decode(data, (ActionType, bytes));\n\n // this event is emitted even though the actionType may not be valid\n MultichainEventUtils.emitMultichainBridgeAction(eventEmitter, address(this), account, srcChainId, uint256(actionType));\n\n /// @dev relayParams.fee.feeToken must default to WNT when feeSwapPath is not being used\n /// otherwise reverts with UnexpectedRelayFeeToken\n if (actionType == ActionType.Deposit) {\n _handleDeposit(account, srcChainId, actionType, actionData);\n } else if (actionType == ActionType.GlvDeposit) {\n _handleGlvDeposit(account, srcChainId, actionType, actionData);\n } else if (actionType == ActionType.SetTraderReferralCode) {\n _handleSetTraderReferralCode(account, srcChainId, actionType, actionData);\n } else if (actionType == ActionType.Withdrawal) {\n _handleWithdrawal(account, srcChainId, actionType, actionData);\n } else if (actionType == ActionType.GlvWithdrawal) {\n _handleGlvWithdrawal(account, srcChainId, actionType, actionData);\n }\n }\n }\n\n /**\n * Bridges tokens from the current chain to a source chain using Stargate protocol\n * @dev Processes a cross-chain transfer of tokens from user's multichain balance\n * @dev Called by MultichainTransferRouter\n * This function:\n * 1. Approves tokens to be spent by Stargate\n * 2. Prepares the necessary parameters and quotes fees\n * 3. Transfers the bridging fee (in WNT) from user's multichain balance\n * 4. Unwraps WNT to ETH to pay for the cross-chain fee\n * 5. Transfers the tokens to be bridged from user's multichain balance\n * 6. Calls Stargate to initiate the cross-chain transfer\n *\n * @param params A struct containing:\n * - provider: Address of the Stargate pool\n * - account: User account bridging tokens\n * - token: Address of token being bridged\n * - amount: Amount of tokens to bridge\n * - srcChainId: Source chain ID (for multichain balance accounting)\n * - data: ABI-encoded destination endpoint ID (dstEid)\n * @return The amount of tokens bridged out (may be slightly different from params.amount after LZ precision/path limits adjustments)\n */\n function bridgeOut(address account, uint256 srcChainId, IRelayUtils.BridgeOutParams memory params) external onlyController returns (uint256) {\n IStargate stargate = IStargate(params.provider);\n\n address wnt = dataStore.getAddress(Keys.WNT);\n\n if (stargate.token() == address(0x0)) {\n // `stargate` is StargatePoolNative\n if (params.token != wnt) {\n revert Errors.InvalidBridgeOutToken(params.token);\n }\n } else {\n // `stargate` is e.g. StargatePoolUSDC\n if (params.token != stargate.token()) {\n revert Errors.InvalidBridgeOutToken(params.token);\n }\n }\n\n BridgeOutCache memory cache;\n cache.dstEid = abi.decode(params.data, (uint32));\n\n if (srcChainId != dataStore.getUint(Keys.eidToSrcChainId(cache.dstEid))) {\n revert Errors.InvalidEid(cache.dstEid);\n }\n\n (cache.valueToSend, cache.sendParam, cache.messagingFee, cache.receipt) = prepareSend(\n stargate,\n params.amount,\n params.minAmountOut,\n account,\n cache.dstEid\n );\n\n // LZ/Stargate would round down the `amount` to 6 decimals precision / apply path limits\n params.amount = cache.receipt.amountSentLD;\n\n // transferOut bridging fee amount of wnt from user's multichain balance into this contract\n // for StargatePoolNative, amountSentLD is added on top of the bridging fee\n MultichainUtils.transferOut(\n dataStore,\n eventEmitter,\n multichainVault,\n wnt, // token\n account,\n address(this), // receiver\n cache.valueToSend, // bridge out fee (+ amountSentLD for native token transfers)\n srcChainId\n );\n\n IWNT(wnt).withdraw(cache.valueToSend);\n\n // if Stagrate.token() is the ZeroAddress:\n // - amountSentLD was already added to valueToSend and transferred/unwrapped with the bridging fee\n // - approval is not needed (since native tokens are being bridged)\n if (stargate.token() != address(0x0)) {\n // `stargate` is e.g. StargatePoolUSDC\n // transferOut amount of tokens from user's multichain balance into this contract\n MultichainUtils.transferOut(\n dataStore,\n eventEmitter,\n multichainVault,\n params.token,\n account,\n address(this), // receiver\n params.amount,\n srcChainId\n );\n\n IERC20(params.token).approve(params.provider, params.amount);\n }\n\n (cache.msgReceipt, /* OFTReceipt memory oftReceipt */) = stargate.send{ value: cache.valueToSend }(\n cache.sendParam,\n cache.messagingFee,\n address(this) // refundAddress\n );\n\n // fee refunds are send back to this contract, converted to wrapped native token,\n // sent to multichainVault and user's multichain balance is increased\n if (cache.msgReceipt.fee.nativeFee < cache.messagingFee.nativeFee) {\n TokenUtils.depositAndSendWrappedNativeToken(\n dataStore,\n address(multichainVault), // receiver\n cache.messagingFee.nativeFee - cache.msgReceipt.fee.nativeFee // refund amount\n );\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n wnt, // token\n account,\n 0 // srcChainId\n );\n }\n\n return params.amount;\n }\n\n function prepareSend(\n IStargate stargate,\n uint256 amount,\n uint256 minAmountOut,\n address receiver,\n uint32 _dstEid\n )\n private\n view\n returns (\n uint256 valueToSend,\n SendParam memory sendParam,\n MessagingFee memory messagingFee,\n OFTReceipt memory receipt\n )\n {\n sendParam = SendParam({\n dstEid: _dstEid,\n to: Cast.toBytes32(receiver),\n amountLD: amount,\n minAmountLD: minAmountOut,\n extraOptions: bytes(\"\"),\n composeMsg: bytes(\"\"),\n oftCmd: \"\"\n });\n\n (, , receipt) = stargate.quoteOFT(sendParam);\n sendParam.minAmountLD = receipt.amountReceivedLD;\n\n messagingFee = stargate.quoteSend(sendParam, false);\n valueToSend = messagingFee.nativeFee;\n\n if (stargate.token() == address(0x0)) {\n valueToSend += receipt.amountSentLD;\n }\n }\n\n function _decodeLzComposeMsg(bytes calldata message) private view returns (address, uint256, uint256, bytes memory) {\n uint256 amountLD = OFTComposeMsgCodec.amountLD(message);\n\n uint32 srcEid = OFTComposeMsgCodec.srcEid(message);\n uint256 srcChainId = dataStore.getUint(Keys.eidToSrcChainId(srcEid));\n\n bytes memory composeMessage = OFTComposeMsgCodec.composeMsg(message);\n (address account, bytes memory data) = abi.decode(composeMessage, (address, bytes));\n\n return (account, srcChainId, amountLD, data);\n }\n\n function _areValidTransferRequests(IRelayUtils.TransferRequests memory transferRequests) private pure returns (bool) {\n if (\n transferRequests.tokens.length != transferRequests.receivers.length ||\n transferRequests.tokens.length != transferRequests.amounts.length\n ) {\n return false;\n }\n for (uint256 i = 0; i < transferRequests.tokens.length; i++) {\n if (\n transferRequests.tokens[i] == address(0) ||\n transferRequests.receivers[i] == address(0) ||\n transferRequests.amounts[i] == 0\n ) {\n return false;\n }\n }\n return true;\n }\n\n /// @dev long/short tokens are deposited from user's multichain balance\n /// GM tokens are minted and transferred to user's multichain balance\n function _handleDeposit(\n address account,\n uint256 srcChainId,\n ActionType actionType,\n bytes memory actionData\n ) private {\n (\n IRelayUtils.RelayParams memory relayParams,\n IRelayUtils.TransferRequests memory transferRequests,\n IDepositUtils.CreateDepositParams memory depositParams\n ) = abi.decode(actionData, (IRelayUtils.RelayParams, IRelayUtils.TransferRequests, IDepositUtils.CreateDepositParams));\n\n if (_areValidTransferRequests(transferRequests)) {\n uint256 estimatedGasLimit = GasUtils.estimateCreateDepositGasLimit(dataStore);\n _validateGasLeft(estimatedGasLimit);\n\n try multichainGmRouter.createDeposit(\n relayParams,\n account,\n srcChainId,\n transferRequests,\n depositParams\n ) {\n } catch Error(string memory reason) {\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n }\n }\n }\n\n /// @dev long/short/GM tokens are deposited from user's multichain balance\n /// GLV tokens are minted and transferred to user's multichain balance\n function _handleGlvDeposit(\n address account,\n uint256 srcChainId,\n ActionType actionType,\n bytes memory actionData\n ) private {\n (\n IRelayUtils.RelayParams memory relayParams,\n IRelayUtils.TransferRequests memory transferRequests,\n IGlvDepositUtils.CreateGlvDepositParams memory glvDepositParams\n ) = abi.decode(actionData, (IRelayUtils.RelayParams, IRelayUtils.TransferRequests, IGlvDepositUtils.CreateGlvDepositParams));\n\n if (_areValidTransferRequests(transferRequests)) {\n uint256 estimatedGasLimit = GasUtils.estimateCreateGlvDepositGasLimit(dataStore);\n _validateGasLeft(estimatedGasLimit);\n\n try multichainGlvRouter.createGlvDeposit(\n relayParams,\n account,\n srcChainId,\n transferRequests,\n glvDepositParams\n ) {\n } catch Error(string memory reason) {\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n }\n }\n }\n\n /// @dev `account` is expected to be `msg.sender` from the source chain, as\n /// MultichainOrderRouter would use it to validate the signature.\n function _handleSetTraderReferralCode(\n address account,\n uint256 srcChainId,\n ActionType actionType,\n bytes memory actionData\n ) private {\n (\n IRelayUtils.RelayParams memory relayParams,\n bytes32 referralCode\n ) = abi.decode(actionData, (IRelayUtils.RelayParams, bytes32));\n\n uint256 estimatedGasLimit = GasUtils.estimateSetTraderReferralCodeGasLimit(dataStore);\n _validateGasLeft(estimatedGasLimit);\n\n try multichainOrderRouter.setTraderReferralCode(relayParams, account, srcChainId, referralCode) {\n } catch Error(string memory reason) {\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n }\n }\n\n function _handleWithdrawal(\n address account,\n uint256 srcChainId,\n ActionType actionType,\n bytes memory actionData\n ) private {\n (\n IRelayUtils.RelayParams memory relayParams,\n IRelayUtils.TransferRequests memory transferRequests,\n IWithdrawalUtils.CreateWithdrawalParams memory withdrawalParams\n ) = abi.decode(actionData, (IRelayUtils.RelayParams, IRelayUtils.TransferRequests, IWithdrawalUtils.CreateWithdrawalParams));\n\n if (_areValidTransferRequests(transferRequests)) {\n uint256 estimatedGasLimit = GasUtils.estimateCreateWithdrawalGasLimit(dataStore);\n _validateGasLeft(estimatedGasLimit);\n\n try multichainGmRouter.createWithdrawal(\n relayParams,\n account,\n srcChainId,\n transferRequests,\n withdrawalParams\n ) {\n } catch Error(string memory reason) {\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n }\n }\n }\n\n function _handleGlvWithdrawal(\n address account,\n uint256 srcChainId,\n ActionType actionType,\n bytes memory actionData\n ) private {\n (\n IRelayUtils.RelayParams memory relayParams,\n IRelayUtils.TransferRequests memory transferRequests,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams memory glvWithdrawalParams\n ) = abi.decode(actionData, (IRelayUtils.RelayParams, IRelayUtils.TransferRequests, IGlvWithdrawalUtils.CreateGlvWithdrawalParams));\n\n if (_areValidTransferRequests(transferRequests)) {\n uint256 estimatedGasLimit = GasUtils.estimateCreateGlvWithdrawalGasLimit(dataStore);\n _validateGasLeft(estimatedGasLimit);\n\n try multichainGlvRouter.createGlvWithdrawal(\n relayParams,\n account,\n srcChainId,\n transferRequests,\n glvWithdrawalParams\n ) {\n } catch Error(string memory reason) {\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n MultichainEventUtils.emitMultichainBridgeActionFailed(eventEmitter, address(this), account, srcChainId, uint256(actionType), reason);\n }\n }\n }\n\n function _validateGasLeft(uint256 estimatedGasLimit) internal view {\n uint256 gas = gasleft();\n if (gas < estimatedGasLimit) {\n revert Errors.InsufficientGasLeft(gas, estimatedGasLimit);\n }\n }\n\n /**\n * @notice Withdraws tokens which have been locked in this contract due to potential errors in lzCompose (e.g. incorrect message format).\n * @dev Callable through the timelock contract.\n * @param token The address of the token to withdraw.\n * @param receiver The address receiving the withdrawn tokens.\n * @param amount The amount of tokens to withdraw.\n */\n function withdrawTokens(address token, address receiver, uint256 amount) external onlyController {\n if (amount == 0) {\n revert Errors.EmptyWithdrawalAmount();\n }\n\n if (token == address(0)) {\n TokenUtils.sendNativeToken(dataStore, receiver, amount);\n } else {\n TokenUtils.transfer(dataStore, token, receiver, amount);\n }\n }\n\n /// @dev Accept ETH from StargatePoolNative and when unwrapping WNT\n receive() external payable {}\n}\n" + }, + "contracts/multichain/MultichainClaimsRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../fee/FeeUtils.sol\";\nimport \"../referral/ReferralUtils.sol\";\nimport \"./MultichainRouter.sol\";\n\n\n/*\n * Fees can be paid from the newly claimed tokens if the recipient is the account.\n * Otherwise, the account must have enough funds to pay fees first.\n */\ncontract MultichainClaimsRouter is MultichainRouter {\n constructor(\n BaseConstructorParams memory params\n ) MultichainRouter(params) BaseRouter(params.router, params.roleStore, params.dataStore, params.eventEmitter) {}\n\n // @dev same logic as withRelay modifier, but different execution order\n // to allow paying the relayFee from newly claimed tokens\n // i.e. _handleRelayBeforeAction is \"delayed\" and executed at the same time as _handleRelayAfterAction\n modifier withRelayForClaims(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bool isSubaccount\n ) {\n uint256 startingGas = gasleft();\n _validateGaslessFeature();\n Contracts memory contracts = _getContracts();\n _;\n // beforeAction \"delayed\" after tokens have been claimed\n _handleRelayBeforeAction(contracts, relayParams, account, srcChainId, isSubaccount);\n _handleRelayAfterAction(contracts, startingGas, account, srcChainId);\n }\n\n function claimFundingFees(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external nonReentrant withRelayForClaims(relayParams, account, srcChainId, false) returns (uint256[] memory) {\n bytes32 structHash = RelayUtils.getClaimFundingFeesStructHash(relayParams, markets, tokens, receiver);\n _validateCall(relayParams, account, structHash, srcChainId);\n return _claimFundingFees(account, srcChainId, markets, tokens, receiver);\n }\n\n function _claimFundingFees(\n address account,\n uint256 srcChainId,\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) private returns (uint256[] memory claimedAmounts) {\n claimedAmounts = FeeUtils.batchClaimFundingFees(\n dataStore,\n eventEmitter,\n markets,\n tokens,\n address(multichainVault), // receiver\n account\n );\n\n for (uint256 i; i < tokens.length; i++) {\n MultichainUtils.recordTransferIn(dataStore, eventEmitter, multichainVault, tokens[i], receiver, srcChainId);\n }\n }\n\n function claimCollateral(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n address[] memory markets,\n address[] memory tokens,\n uint256[] memory timeKeys,\n address receiver\n ) external nonReentrant withRelayForClaims(relayParams, account, srcChainId, false) returns (uint256[] memory) {\n return _claimCollateral(relayParams, account, srcChainId, markets, tokens, timeKeys, receiver);\n }\n\n function _claimCollateral(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n address[] memory markets,\n address[] memory tokens,\n uint256[] memory timeKeys,\n address receiver\n ) private returns (uint256[] memory claimedAmounts) {\n // validation added here instead of claimCollateral to avoid stack too deep error\n bytes32 structHash = RelayUtils.getClaimCollateralStructHash(relayParams, markets, tokens, timeKeys, receiver);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n claimedAmounts = MarketUtils.batchClaimCollateral(\n dataStore,\n eventEmitter,\n markets,\n tokens,\n timeKeys,\n address(multichainVault), // receiver\n account\n );\n\n for (uint256 i; i < tokens.length; i++) {\n MultichainUtils.recordTransferIn(dataStore, eventEmitter, multichainVault, tokens[i], receiver, srcChainId);\n }\n }\n\n function claimAffiliateRewards(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external nonReentrant withRelayForClaims(relayParams, account, srcChainId, false) returns (uint256[] memory) {\n bytes32 structHash = RelayUtils.getClaimAffiliateRewardsStructHash(relayParams, markets, tokens, receiver);\n _validateCall(relayParams, account, structHash, srcChainId);\n return _claimAffiliateRewards(account, srcChainId, markets, tokens, receiver);\n }\n\n function _claimAffiliateRewards(\n address account,\n uint256 srcChainId,\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) private returns (uint256[] memory claimedAmounts) {\n claimedAmounts = ReferralUtils.batchClaimAffiliateRewards(\n dataStore,\n eventEmitter,\n markets,\n tokens,\n address(multichainVault), // receiver\n account\n );\n\n for (uint256 i; i < tokens.length; i++) {\n MultichainUtils.recordTransferIn(dataStore, eventEmitter, multichainVault, tokens[i], receiver, srcChainId);\n }\n }\n}\n" + }, + "contracts/multichain/MultichainEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport { EventEmitter } from \"../event/EventEmitter.sol\";\nimport { EventUtils } from \"../event/EventUtils.sol\";\nimport { Cast } from \"../utils/Cast.sol\";\n\n/**\n * @title MultichainEventUtils\n */\nlibrary MultichainEventUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.StringItems;\n\n /// @param provider the address of the multichain provider for cross-chain action,\n /// or zero address for same-chain action\n function emitMultichainBridgeIn(\n EventEmitter eventEmitter,\n address provider,\n address token,\n address account,\n uint256 amount,\n uint256 srcChainId\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"provider\", provider);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"account\", account);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventData.uintItems.setItem(1, \"srcChainId\", srcChainId);\n\n eventEmitter.emitEventLog1(\"MultichainBridgeIn\", Cast.toBytes32(account), eventData);\n }\n\n function emitMultichainTransferIn(\n EventEmitter eventEmitter,\n address token,\n address account,\n uint256 amount,\n uint256 srcChainId\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"token\", token);\n eventData.addressItems.setItem(1, \"account\", account);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventData.uintItems.setItem(1, \"srcChainId\", srcChainId);\n\n eventEmitter.emitEventLog1(\"MultichainTransferIn\", Cast.toBytes32(account), eventData);\n }\n\n /// @param provider the address of the multichain provider for Deposit/GlvDeposit action types,\n /// or handler address for BridgeOut action type\n function emitMultichainBridgeAction(\n EventEmitter eventEmitter,\n address provider,\n address account,\n uint256 srcChainId,\n uint256 actionType\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"provider\", provider);\n eventData.addressItems.setItem(1, \"account\", account);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"srcChainId\", srcChainId);\n eventData.uintItems.setItem(1, \"actionType\", actionType);\n\n eventEmitter.emitEventLog1(\"MultichainBridgeAction\", Cast.toBytes32(account), eventData);\n }\n\n /// @param provider the address of the multichain provider for Deposit/GlvDeposit action types,\n /// or handler address for BridgeOut action type\n function emitMultichainBridgeActionFailed(\n EventEmitter eventEmitter,\n address provider,\n address account,\n uint256 srcChainId,\n uint256 actionType,\n string memory reason\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"provider\", provider);\n eventData.addressItems.setItem(1, \"account\", account);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"srcChainId\", srcChainId);\n eventData.uintItems.setItem(1, \"actionType\", actionType);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventEmitter.emitEventLog1(\"MultichainBridgeActionFailed\", Cast.toBytes32(account), eventData);\n }\n\n /// @param provider the address of the multichain provider for cross-chain action,\n /// or zero address for same-chain action\n function emitMultichainBridgeOut(\n EventEmitter eventEmitter,\n address provider,\n address token,\n address receiver,\n uint256 amount,\n uint256 srcChainId\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"provider\", provider);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"receiver\", receiver);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventData.uintItems.setItem(1, \"srcChainId\", srcChainId);\n\n eventEmitter.emitEventLog1(\"MultichainBridgeOut\", Cast.toBytes32(receiver), eventData);\n }\n\n function emitMultichainTransferOut(\n EventEmitter eventEmitter,\n address token,\n address account,\n address receiver,\n uint256 amount,\n uint256 srcChainId\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"token\", token);\n eventData.addressItems.setItem(1, \"account\", account);\n eventData.addressItems.setItem(2, \"receiver\", receiver);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventData.uintItems.setItem(1, \"srcChainId\", srcChainId);\n\n eventEmitter.emitEventLog1(\"MultichainTransferOut\", Cast.toBytes32(account), eventData);\n }\n}\n" + }, + "contracts/multichain/MultichainGlvRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../exchange/IGlvDepositHandler.sol\";\nimport \"../exchange/IGlvWithdrawalHandler.sol\";\nimport \"../glv/GlvVault.sol\";\n\nimport \"./IMultichainGlvRouter.sol\";\nimport \"./MultichainRouter.sol\";\n\ncontract MultichainGlvRouter is IMultichainGlvRouter, MultichainRouter {\n using SafeERC20 for IERC20;\n\n IGlvDepositHandler public immutable glvDepositHandler;\n GlvVault public immutable glvVault;\n IGlvWithdrawalHandler public immutable glvWithdrawalHandler;\n\n constructor(\n BaseConstructorParams memory params,\n IGlvDepositHandler _glvDepositHandler,\n IGlvWithdrawalHandler _glvWithdrawalHandler,\n GlvVault _glvVault\n ) MultichainRouter(params) BaseRouter(params.router, params.roleStore, params.dataStore, params.eventEmitter) {\n glvDepositHandler = _glvDepositHandler;\n glvWithdrawalHandler = _glvWithdrawalHandler;\n glvVault = _glvVault;\n }\n\n function createGlvDeposit(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvDepositUtils.CreateGlvDepositParams memory params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32) {\n bytes32 structHash = RelayUtils.getCreateGlvDepositStructHash(relayParams, transferRequests, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n return _createGlvDeposit(account, srcChainId, transferRequests, params);\n }\n\n function _createGlvDeposit(\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvDepositUtils.CreateGlvDepositParams memory params\n ) private returns (bytes32) {\n _processTransferRequests(account, transferRequests, srcChainId);\n\n address wnt = TokenUtils.wnt(dataStore);\n IERC20(wnt).safeTransfer(address(glvVault), params.executionFee);\n\n return glvDepositHandler.createGlvDeposit(account, srcChainId, params);\n }\n\n function createGlvWithdrawal(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams memory params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32) {\n bytes32 structHash = RelayUtils.getCreateGlvWithdrawalStructHash(relayParams, transferRequests, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n _processTransferRequests(account, transferRequests, srcChainId);\n\n address wnt = TokenUtils.wnt(dataStore);\n IERC20(wnt).safeTransfer(address(glvVault), params.executionFee);\n\n return glvWithdrawalHandler.createGlvWithdrawal(account, srcChainId, params);\n }\n}\n" + }, + "contracts/multichain/MultichainGmRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../exchange/IDepositHandler.sol\";\nimport \"../exchange/IWithdrawalHandler.sol\";\nimport \"../exchange/IShiftHandler.sol\";\n\nimport \"../deposit/DepositVault.sol\";\nimport \"../withdrawal/WithdrawalVault.sol\";\nimport \"../shift/ShiftVault.sol\";\n\nimport \"./IMultichainGmRouter.sol\";\nimport \"./MultichainRouter.sol\";\n\ncontract MultichainGmRouter is IMultichainGmRouter, MultichainRouter {\n using SafeERC20 for IERC20;\n\n DepositVault public immutable depositVault;\n IDepositHandler public immutable depositHandler;\n WithdrawalVault public immutable withdrawalVault;\n IWithdrawalHandler public immutable withdrawalHandler;\n ShiftVault public immutable shiftVault;\n IShiftHandler public immutable shiftHandler;\n\n constructor(\n BaseConstructorParams memory params,\n DepositVault _depositVault,\n IDepositHandler _depositHandler,\n WithdrawalVault _withdrawalVault,\n IWithdrawalHandler _withdrawalHandler,\n ShiftVault _shiftVault,\n IShiftHandler _shiftHandler\n ) MultichainRouter(params) BaseRouter(params.router, params.roleStore, params.dataStore, params.eventEmitter) {\n depositVault = _depositVault;\n depositHandler = _depositHandler;\n withdrawalVault = _withdrawalVault;\n withdrawalHandler = _withdrawalHandler;\n shiftVault = _shiftVault;\n shiftHandler = _shiftHandler;\n }\n\n function createDeposit(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IDepositUtils.CreateDepositParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32) {\n bytes32 structHash = RelayUtils.getCreateDepositStructHash(relayParams, transferRequests, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n return _createDeposit(account, srcChainId, transferRequests, params);\n }\n\n function _createDeposit(\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IDepositUtils.CreateDepositParams calldata params\n ) private returns (bytes32) {\n _processTransferRequests(account, transferRequests, srcChainId);\n\n address wnt = TokenUtils.wnt(dataStore);\n IERC20(wnt).safeTransfer(address(depositVault), params.executionFee);\n\n return depositHandler.createDeposit(account, srcChainId, params);\n }\n\n function createWithdrawal(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IWithdrawalUtils.CreateWithdrawalParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32) {\n bytes32 structHash = RelayUtils.getCreateWithdrawalStructHash(relayParams, transferRequests, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n _processTransferRequests(account, transferRequests, srcChainId);\n\n address wnt = TokenUtils.wnt(dataStore);\n IERC20(wnt).safeTransfer(address(withdrawalVault), params.executionFee);\n\n return withdrawalHandler.createWithdrawal(account, srcChainId, params);\n }\n\n function createShift(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.TransferRequests calldata transferRequests,\n IShiftUtils.CreateShiftParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32) {\n bytes32 structHash = RelayUtils.getCreateShiftStructHash(relayParams, transferRequests, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n _processTransferRequests(account, transferRequests, srcChainId);\n\n address wnt = TokenUtils.wnt(dataStore);\n IERC20(wnt).safeTransfer(address(shiftVault), params.executionFee);\n\n return shiftHandler.createShift(account, srcChainId, params);\n }\n}\n" + }, + "contracts/multichain/MultichainOrderRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../referral/IReferralStorage.sol\";\nimport \"./IMultichainOrderRouter.sol\";\nimport \"./MultichainRouter.sol\";\n\ncontract MultichainOrderRouter is IMultichainOrderRouter, MultichainRouter {\n IReferralStorage public immutable referralStorage;\n\n constructor(\n BaseConstructorParams memory params,\n IReferralStorage _referralStorage\n ) MultichainRouter(params) BaseRouter(params.router, params.roleStore, params.dataStore, params.eventEmitter) {\n referralStorage = _referralStorage;\n }\n\n function batch(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.BatchParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32[] memory) {\n bytes32 structHash = RelayUtils.getBatchStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n return\n _batch(\n account,\n srcChainId,\n params.createOrderParamsList,\n params.updateOrderParamsList,\n params.cancelOrderKeys,\n false // isSubaccount\n );\n }\n\n function createOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) returns (bytes32) {\n bytes32 structHash = RelayUtils.getCreateOrderStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n return _createOrder(account, srcChainId, params, false);\n }\n\n function updateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.UpdateOrderParams calldata params\n )\n external\n nonReentrant\n withRelay(relayParams, account, srcChainId, false)\n {\n bytes32 structHash = RelayUtils.getUpdateOrderStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n _updateOrder(account, params, false);\n }\n\n function cancelOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bytes32 key\n )\n external\n nonReentrant\n withRelay(relayParams, account, srcChainId, false)\n {\n bytes32 structHash = RelayUtils.getCancelOrderStructHash(relayParams, key);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n _cancelOrder(account, key);\n }\n\n function setTraderReferralCode(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bytes32 referralCode\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) {\n bytes32 structHash = RelayUtils.getTraderReferralCodeStructHash(relayParams, referralCode);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n referralStorage.setTraderReferralCode(account, referralCode);\n }\n}\n" + }, + "contracts/multichain/MultichainReader.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { AddressCast } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol\";\nimport { MessagingParams, MessagingFee, MessagingReceipt, ILayerZeroEndpointV2 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { Origin } from \"@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol\";\nimport { EVMCallRequestV1, EVMCallComputeV1, ReadCodecV1 } from \"@layerzerolabs/oapp-evm/contracts/oapp/libs/ReadCodecV1.sol\";\nimport { GUID } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/GUID.sol\";\nimport { MultichainReaderUtils } from \"./MultichainReaderUtils.sol\";\nimport { IOriginator } from \"./IOriginator.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys2.sol\";\nimport \"../role/RoleModule.sol\";\nimport \"../event/EventEmitter.sol\";\n\ncontract MultichainReader is RoleModule {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n\n uint64 internal constant SENDER_VERSION = 1;\n uint64 internal constant RECEIVER_VERSION = 2;\n uint8 internal constant WORKER_ID = 1;\n uint8 internal constant OPTION_TYPE_LZREAD = 5;\n uint16 internal constant TYPE_3 = 3;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n ILayerZeroEndpointV2 public immutable endpoint;\n uint32 public immutable currentChainEid;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n address _endpoint\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n endpoint = ILayerZeroEndpointV2(_endpoint);\n currentChainEid = endpoint.eid();\n }\n\n function setDelegate(address _delegate) external onlyTimelockMultisig {\n endpoint.setDelegate(_delegate);\n }\n\n function sendReadRequests(\n MultichainReaderUtils.ReadRequestInputs[] calldata readRequestInputs,\n MultichainReaderUtils.ExtraOptionsInputs calldata extraOptionsInputs\n ) external payable onlyController returns (MessagingReceipt memory) {\n address originator = msg.sender;\n bool isAuthorized = dataStore.getBool(Keys2.multichainAuthorizedOriginatorsKey(originator));\n if (!isAuthorized) {\n revert Errors.Unauthorized(originator, \"Only Originator\");\n }\n\n address self = address(this);\n uint32 readChannel = uint32(dataStore.getUint(Keys2.MULTICHAIN_READ_CHANNEL));\n bytes32 selfBytes32 = AddressCast.toBytes32(self);\n uint64 nonce = endpoint.outboundNonce(self, readChannel, selfBytes32) + 1;\n bytes32 guid = GUID.generate(nonce, currentChainEid, self, readChannel, selfBytes32);\n dataStore.setAddress(Keys2.multichainGuidToOriginatorKey(guid), originator);\n\n bytes memory cmd = _getCmd(readRequestInputs);\n MessagingReceipt memory messagingReceipt = _lzSend(\n readChannel,\n cmd,\n _extraOptions(extraOptionsInputs),\n MessagingFee(msg.value, 0),\n payable(originator)\n );\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"originator\", originator);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"guid\", guid);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"cmd\", cmd);\n\n eventEmitter.emitEventLog1(\"sendReadRequests\", AddressCast.toBytes32(originator), eventData);\n\n return (messagingReceipt);\n }\n\n function lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable {\n // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.\n if (address(endpoint) != msg.sender) revert Errors.Unauthorized(msg.sender, \"Only Endpoint\");\n\n // Ensure that the sender matches the expected peer for the source endpoint.\n if (_getPeerOrRevert(_origin.srcEid) != _origin.sender)\n revert Errors.Unauthorized(AddressCast.toAddress(_origin.sender), \"Only Peer\");\n\n // Call the internal OApp implementation of lzReceive.\n _lzReceive(_origin, _guid, _message, _executor, _extraData);\n }\n\n function peers(uint32 _eid) external view returns (bytes32 peer) {\n peer = dataStore.getBytes32(Keys2.multichainPeersKey(_eid));\n }\n\n function quoteReadFee(\n MultichainReaderUtils.ReadRequestInputs[] calldata readRequestInputs,\n MultichainReaderUtils.ExtraOptionsInputs calldata extraOptionsInputs\n ) external view returns (MessagingFee memory fee) {\n return\n _quote(\n uint32(dataStore.getUint(Keys2.MULTICHAIN_READ_CHANNEL)),\n _getCmd(readRequestInputs),\n _extraOptions(extraOptionsInputs)\n );\n }\n\n function isComposeMsgSender(\n Origin calldata /*_origin*/,\n bytes calldata /*_message*/,\n address _sender\n ) external view returns (bool) {\n return _sender == address(this);\n }\n\n function allowInitializePath(Origin calldata origin) external view returns (bool) {\n return dataStore.getBytes32(Keys2.multichainPeersKey(origin.srcEid)) == origin.sender;\n }\n\n function lzReduce(bytes calldata _cmd, bytes[] calldata _responses) external pure returns (bytes memory) {\n bytes memory responses;\n for (uint256 i = 0; i < _responses.length; i++) {\n responses = bytes.concat(responses, _responses[i]);\n }\n\n (, , EVMCallComputeV1 memory computeRequest) = ReadCodecV1.decode(_cmd);\n return bytes.concat(abi.encodePacked(computeRequest.blockNumOrTimestamp), responses);\n }\n\n function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) external pure returns (uint64 nonce) {\n return 0;\n }\n\n function oAppVersion() external pure returns (uint64 senderVersion, uint64 receiverVersion) {\n return (SENDER_VERSION, RECEIVER_VERSION);\n }\n\n function _lzSend(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n MessagingFee memory _fee,\n address _refundAddress\n ) internal returns (MessagingReceipt memory receipt) {\n // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.\n uint256 messageValue = _payNative(_fee.nativeFee);\n\n return\n // solhint-disable-next-line check-send-result\n endpoint.send{ value: messageValue }(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, false),\n _refundAddress\n );\n }\n\n function _lzReceive(\n Origin calldata /*_origin*/,\n bytes32 _guid,\n bytes calldata _message,\n address /*_executor*/,\n bytes calldata /*_extraData*/\n ) internal {\n uint256 timestamp = uint64(bytes8(_message[:8]));\n bytes memory message = _message[8:_message.length];\n\n address originator = dataStore.getAddress(Keys2.multichainGuidToOriginatorKey(_guid));\n MultichainReaderUtils.ReceivedData memory receivedData = MultichainReaderUtils.ReceivedData(timestamp, message);\n IOriginator(originator).processLzReceive(_guid, receivedData);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"originator\", originator);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"guid\", _guid);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"message\", _message);\n\n eventEmitter.emitEventLog1(\"lzReceive\", AddressCast.toBytes32(originator), eventData);\n }\n\n function _payNative(uint256 _nativeFee) internal returns (uint256 nativeFee) {\n if (msg.value != _nativeFee) revert Errors.InsufficientMultichainNativeFee(msg.value);\n return _nativeFee;\n }\n\n function _getCmd(\n MultichainReaderUtils.ReadRequestInputs[] calldata readRequestInputs\n ) internal view returns (bytes memory) {\n uint64 timestamp = uint64(block.timestamp);\n uint256 readRequestCount = readRequestInputs.length;\n EVMCallRequestV1[] memory readRequests = new EVMCallRequestV1[](readRequestCount);\n for (uint256 i; i < readRequestCount; i++) {\n uint32 targetChainEid = readRequestInputs[i].targetChainEid;\n readRequests[i] = EVMCallRequestV1({\n appRequestLabel: uint16(i + 1), // Application-specific label for tracking\n targetEid: targetChainEid, // Endpoint ID of the target chain\n isBlockNum: false, // Use timestamp instead of block number\n blockNumOrTimestamp: timestamp, // Timestamp to read the state at\n confirmations: uint16(dataStore.getUint(Keys2.multichainConfirmationsKey(targetChainEid))), // Number of confirmations to wait for finality\n to: readRequestInputs[i].target, // Address of the contract to call\n callData: readRequestInputs[i].callData // Encoded function call data\n });\n }\n\n EVMCallComputeV1 memory computeRequest = EVMCallComputeV1({\n computeSetting: 1, // Use lzReduce()\n targetEid: currentChainEid, // Endpoint ID of the current chain\n isBlockNum: false, // Use timestamp instead of block number\n blockNumOrTimestamp: timestamp, // Timestamp to execute the compute at\n confirmations: uint16(dataStore.getUint(Keys2.multichainConfirmationsKey(currentChainEid))), // Number of confirmations to wait for finality\n to: address(this) // Address of this contract to lzReduce\n });\n\n return ReadCodecV1.encode(0, readRequests, computeRequest);\n }\n\n function _getPeerOrRevert(uint32 _eid) internal view returns (bytes32) {\n bytes32 peer = dataStore.getBytes32(Keys2.multichainPeersKey(_eid));\n if (peer == bytes32(0)) revert Errors.EmptyPeer(_eid);\n return peer;\n }\n\n function _quote(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options\n ) internal view returns (MessagingFee memory fee) {\n return\n endpoint.quote(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, false),\n address(this)\n );\n }\n\n function _extraOptions(\n MultichainReaderUtils.ExtraOptionsInputs calldata extraOptionsInputs\n ) internal pure returns (bytes memory) {\n bytes memory option = extraOptionsInputs.msgValue == 0\n ? abi.encodePacked(extraOptionsInputs.gasLimit, extraOptionsInputs.returnDataSize)\n : abi.encodePacked(\n extraOptionsInputs.gasLimit,\n extraOptionsInputs.returnDataSize,\n extraOptionsInputs.msgValue\n );\n return\n abi.encodePacked(\n abi.encodePacked(TYPE_3),\n WORKER_ID,\n uint16(option.length) + 1, // +1 for optionType\n OPTION_TYPE_LZREAD,\n option\n );\n }\n}\n" + }, + "contracts/multichain/MultichainReaderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nlibrary MultichainReaderUtils {\n struct ReadRequestInputs {\n uint32 targetChainEid;\n address target;\n bytes callData;\n }\n\n struct ExtraOptionsInputs {\n uint128 gasLimit;\n uint32 returnDataSize;\n uint128 msgValue;\n }\n\n struct ReceivedData {\n uint256 timestamp;\n bytes readData;\n }\n}\n" + }, + "contracts/multichain/MultichainRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/relay/BaseGelatoRelayRouter.sol\";\n\nimport \"./MultichainUtils.sol\";\n\nabstract contract MultichainRouter is BaseGelatoRelayRouter {\n struct BaseConstructorParams {\n Router router;\n RoleStore roleStore;\n DataStore dataStore;\n EventEmitter eventEmitter;\n IOracle oracle;\n OrderVault orderVault;\n IOrderHandler orderHandler;\n ISwapHandler swapHandler;\n IExternalHandler externalHandler;\n MultichainVault multichainVault;\n }\n\n MultichainVault public immutable multichainVault;\n\n constructor(\n BaseConstructorParams memory params\n ) BaseGelatoRelayRouter(params.oracle, params.orderHandler, params.orderVault, params.swapHandler, params.externalHandler) {\n multichainVault = params.multichainVault;\n }\n\n function _processTransferRequests(\n address account,\n IRelayUtils.TransferRequests calldata transferRequests,\n uint256 srcChainId\n ) internal {\n if (\n transferRequests.tokens.length != transferRequests.receivers.length ||\n transferRequests.tokens.length != transferRequests.amounts.length\n ) {\n revert Errors.InvalidTransferRequestsLength();\n }\n\n for (uint256 i = 0; i < transferRequests.tokens.length; i++) {\n _sendTokens(\n account,\n transferRequests.tokens[i],\n transferRequests.receivers[i],\n transferRequests.amounts[i],\n srcChainId\n );\n }\n }\n\n function _isMultichain() internal pure override returns (bool) {\n return true;\n }\n\n function _sendTokens(\n address account,\n address token,\n address receiver,\n uint256 amount,\n uint256 srcChainId\n ) internal override {\n AccountUtils.validateReceiver(receiver);\n MultichainUtils.transferOut(\n dataStore,\n eventEmitter,\n multichainVault,\n token,\n account,\n receiver,\n amount,\n srcChainId\n );\n }\n\n function _transferResidualFee(\n address wnt,\n address account,\n uint256 residualFee,\n uint256 srcChainId\n ) internal override {\n TokenUtils.transfer(dataStore, wnt, address(multichainVault), residualFee);\n MultichainUtils.recordTransferIn(dataStore, eventEmitter, multichainVault, wnt, account, srcChainId);\n }\n\n function _recordRefundedAmounts(\n address account,\n uint256 srcChainId,\n address[] calldata refundTokens,\n address[] calldata refundReceivers\n ) internal override {\n // equality length for refundTokens and refundReceivers is validated in the external handler\n for (uint256 i; i < refundReceivers.length; i++) {\n if (refundReceivers[i] == address(multichainVault)) {\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n refundTokens[i],\n account,\n srcChainId\n );\n }\n }\n }\n}\n" + }, + "contracts/multichain/MultichainSubaccountRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../router/Router.sol\";\nimport \"../router/relay/SubaccountRouterUtils.sol\";\nimport \"./MultichainRouter.sol\";\n\ncontract MultichainSubaccountRouter is MultichainRouter {\n mapping(address => uint256) public subaccountApprovalNonces;\n\n constructor(\n BaseConstructorParams memory params\n ) MultichainRouter(params) BaseRouter(params.router, params.roleStore, params.dataStore, params.eventEmitter) {}\n\n // @note all params except subaccount/srcChainId should be part of the corresponding struct hash\n function batch(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n uint256 srcChainId,\n address subaccount,\n IRelayUtils.BatchParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, true) returns (bytes32[] memory) {\n _handleBatch(\n relayParams,\n subaccountApproval,\n account,\n srcChainId,\n subaccount,\n params\n );\n\n return _batch(\n account,\n srcChainId,\n params.createOrderParamsList,\n params.updateOrderParamsList,\n params.cancelOrderKeys,\n true // isSubaccount\n );\n }\n\n // @dev needed to keep `batch` under the stack limit\n function _handleBatch(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n uint256 srcChainId,\n address subaccount,\n IRelayUtils.BatchParams calldata params\n ) private {\n bytes32 structHash = RelayUtils.getBatchStructHash(relayParams, subaccountApproval, account, params);\n _validateCall(relayParams, subaccount, structHash, srcChainId);\n\n for (uint256 i = 0; i < params.createOrderParamsList.length; i++) {\n SubaccountUtils.validateCreateOrderParams(account, params.createOrderParamsList[i]);\n }\n\n uint256 actionsCount = params.createOrderParamsList.length +\n params.updateOrderParamsList.length +\n params.cancelOrderKeys.length;\n\n _handleSubaccountOrderAction(account, srcChainId, subaccount, actionsCount, subaccountApproval);\n }\n\n // @note all params except subaccount/srcChainId should be part of the corresponding struct hash\n function createOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n uint256 srcChainId,\n address subaccount,\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, true) returns (bytes32) {\n _handleCreateOrder(relayParams, subaccountApproval, account, srcChainId, subaccount, params);\n\n return\n _createOrder(\n account,\n srcChainId,\n params,\n true // isSubaccount\n );\n }\n\n // @dev needed to keep `createOrder` under the stack limit\n function _handleCreateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n uint256 srcChainId,\n address subaccount,\n IBaseOrderUtils.CreateOrderParams calldata params\n ) private {\n bytes32 structHash = RelayUtils.getCreateOrderStructHash(relayParams, subaccountApproval, account, params);\n _validateCall(relayParams, subaccount, structHash, srcChainId);\n SubaccountUtils.validateCreateOrderParams(account, params);\n _handleSubaccountOrderAction(account, srcChainId, subaccount, 1, subaccountApproval);\n }\n\n // @note all params except subaccount/srcChainId should be part of the corresponding struct hash\n function updateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n uint256 srcChainId,\n address subaccount,\n IRelayUtils.UpdateOrderParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, true) {\n _handleUpdateOrder(relayParams, subaccountApproval, account, srcChainId, subaccount, params);\n _updateOrder(\n account,\n params,\n true // isSubaccount\n );\n }\n\n // @dev needed to keep `updateOrder` under the stack limit\n function _handleUpdateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n uint256 srcChainId,\n address subaccount,\n IRelayUtils.UpdateOrderParams calldata params\n ) private {\n bytes32 structHash = RelayUtils.getUpdateOrderStructHash(relayParams, subaccountApproval, account, params);\n _validateCall(relayParams, subaccount, structHash, srcChainId);\n _handleSubaccountOrderAction(account, srcChainId, subaccount, 1, subaccountApproval);\n }\n\n // @note all params except subaccount/srcChainId should be part of the corresponding struct hash\n function cancelOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n uint256 srcChainId,\n address subaccount,\n bytes32 key\n ) external nonReentrant withRelay(relayParams, account, srcChainId, true) {\n _handleCancelOrder(relayParams, subaccountApproval, account, srcChainId, subaccount, key);\n _cancelOrder(account, key);\n }\n\n // @dev needed to keep `cancelOrder` under the stack limit\n function _handleCancelOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n uint256 srcChainId,\n address subaccount,\n bytes32 key\n ) private {\n bytes32 structHash = RelayUtils.getCancelOrderStructHash(relayParams, subaccountApproval, account, key);\n _validateCall(relayParams, subaccount, structHash, srcChainId);\n _handleSubaccountOrderAction(account, srcChainId, subaccount, 1, subaccountApproval);\n }\n\n // @note all params except account/srcChainId should be part of the corresponding struct hash\n function removeSubaccount(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n address subaccount\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) {\n // isSubaccount=false is passed to `withRelay` modifier because this action is signed by the main account\n bytes32 structHash = RelayUtils.getRemoveSubaccountStructHash(relayParams, subaccount);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n SubaccountUtils.removeSubaccount(dataStore, eventEmitter, account, subaccount);\n }\n\n function _handleSubaccountOrderAction(\n address account,\n uint256 srcChainId,\n address subaccount,\n uint256 actionsCount,\n SubaccountApproval calldata subaccountApproval\n ) private {\n SubaccountRouterUtils.handleSubaccountAction(\n dataStore,\n eventEmitter,\n account,\n srcChainId,\n subaccount,\n Keys.SUBACCOUNT_ORDER_ACTION, // actionType\n actionsCount,\n subaccountApproval,\n subaccountApprovalNonces\n );\n }\n}\n" + }, + "contracts/multichain/MultichainTransferRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"./MultichainRouter.sol\";\nimport \"./IMultichainTransferRouter.sol\";\n\ncontract MultichainTransferRouter is IMultichainTransferRouter, Initializable, MultichainRouter {\n IMultichainProvider public multichainProvider;\n address private deployer;\n\n constructor(\n BaseConstructorParams memory params\n ) MultichainRouter(params) BaseRouter(params.router, params.roleStore, params.dataStore, params.eventEmitter) {\n deployer = msg.sender;\n }\n\n function initialize(address _multichainProvider) external initializer {\n if (msg.sender != deployer) {\n revert Errors.InvalidInitializer();\n }\n if (_multichainProvider == address(0)) {\n revert Errors.InvalidMultichainProvider(address(0));\n }\n multichainProvider = IMultichainProvider(_multichainProvider);\n }\n\n /**\n * payable function so that it can be called as a multicall\n * this would be used to move user's funds from their Arbitrum account into their multichain balance\n * @dev payable is necessary because, when bridging in WNT the user sends ETH along with the transaction (via multicall)\n */\n function bridgeIn(address account, address token) external payable nonReentrant {\n uint256 amount = MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n token,\n account,\n 0 // srcChainId is the current block.chainId\n );\n MultichainEventUtils.emitMultichainBridgeIn(\n eventEmitter,\n address(0),\n token,\n account,\n amount,\n 0 // srcChainId is the current block.chainId\n );\n }\n\n /*\n * Bridge out funds recorded under the account\n * Can be used for same-chain or cross-chain withdrawals\n */\n function bridgeOut(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n IRelayUtils.BridgeOutParams calldata params\n ) external nonReentrant withRelay(relayParams, account, srcChainId, false) {\n bytes32 structHash = RelayUtils.getBridgeOutStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, srcChainId);\n\n _bridgeOut(account, srcChainId, params);\n }\n\n /*\n * Bridge out funds recorded under the account\n * Used to automatically bridge out GM/GLV token after executeDeposit/executeGlvDeposit\n */\n function bridgeOutFromController(\n address account,\n uint256 srcChainId,\n uint256 desChainId,\n uint256 deadline,\n IRelayUtils.BridgeOutParams calldata params\n ) external nonReentrant onlyController {\n // cross-chain GM/GLV withdrawals are not allowed when the deposit was made natively (srcChainId == 0)\n if (srcChainId == 0) {\n return;\n }\n\n _validateCallWithoutSignature(\n srcChainId,\n desChainId,\n deadline,\n 0 // tokenPermits.length\n );\n\n _bridgeOut(account, srcChainId, params);\n }\n\n /*\n * Bridge out funds recorded under the account OR the smart wallet\n * Can be used for same-chain withdrawals only\n * This would be used by the smart wallets to withdraw funds from the multichain vault\n */\n function transferOut(IRelayUtils.BridgeOutParams calldata params) external nonReentrant {\n address account = msg.sender;\n _bridgeOut(account, block.chainid, params);\n }\n\n function _bridgeOut(address account, uint256 srcChainId, IRelayUtils.BridgeOutParams calldata params) internal {\n if (params.amount == 0) {\n return;\n }\n\n if (srcChainId == block.chainid) {\n // same-chain withdrawal: funds are sent directly to the user's wallet\n MultichainUtils.transferOut(\n dataStore,\n eventEmitter,\n multichainVault,\n params.token,\n account,\n account, // receiver\n params.amount,\n srcChainId\n );\n\n MultichainEventUtils.emitMultichainBridgeOut(\n eventEmitter,\n address(0), // provider\n params.token,\n account,\n params.amount, // amount\n 0 // srcChainId is the current block.chainId\n );\n } else {\n // cross-chain withdrawal: using the multichain provider, funds are bridged to the src chain\n MultichainUtils.validateMultichainProvider(dataStore, params.provider);\n\n // transfer funds (amount + bridging fee) from user's multichain balance to multichainProvider\n // and execute the bridge out to srcChain\n uint256 amountOut = multichainProvider.bridgeOut(\n account,\n srcChainId,\n IRelayUtils.BridgeOutParams({\n token: params.token,\n amount: params.amount,\n minAmountOut: params.minAmountOut,\n provider: params.provider,\n data: params.data\n })\n );\n\n MultichainEventUtils.emitMultichainBridgeOut(\n eventEmitter,\n address(multichainProvider),\n params.token,\n account,\n amountOut, // amount\n srcChainId\n );\n }\n }\n}\n" + }, + "contracts/multichain/MultichainUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"./MultichainVault.sol\";\nimport \"./MultichainEventUtils.sol\";\nimport \"./IMultichainProvider.sol\";\n\n/**\n * @title MultichainUtils\n */\nlibrary MultichainUtils {\n using SafeERC20 for IERC20;\n\n /**\n * Records a deposit from another chain. IMultichainProvider has CONTROLLER role\n * @param multichainProvider the multichain provider contract\n * @param token address of the token being deposited\n * @param account user address on the source chain\n * @param srcChainId id of the source chain\n */\n function recordBridgeIn(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n IMultichainProvider multichainProvider,\n address token,\n address account,\n uint256 srcChainId\n ) external {\n // token should have been transferred to multichainVault by IMultichainProvider\n uint256 amount = multichainVault.recordTransferIn(token);\n\n if (amount == 0) {\n revert Errors.EmptyMultichainTransferInAmount(account, token);\n }\n\n _increaseMultichainBalance(dataStore, eventEmitter, account, token, amount, srcChainId);\n\n MultichainEventUtils.emitMultichainBridgeIn(\n eventEmitter,\n address(multichainProvider),\n token,\n account,\n amount,\n srcChainId\n );\n }\n\n /**\n * Records a transfer of tokens into the multichain vault\n * @param account user address on the source chain\n * @param token address of the token being transferred\n * @param srcChainId id of the source chain\n */\n function recordTransferIn(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n address token,\n address account,\n uint256 srcChainId\n ) external returns (uint256) {\n // token should have been transferred to multichainVault\n uint256 amount = multichainVault.recordTransferIn(token);\n if (amount == 0) {\n return 0;\n }\n\n _increaseMultichainBalance(dataStore, eventEmitter, account, token, amount, srcChainId);\n\n return amount;\n }\n\n function _increaseMultichainBalance(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address token,\n uint256 amount,\n uint256 srcChainId\n ) private {\n dataStore.incrementUint(Keys.multichainBalanceKey(account, token), amount);\n MultichainEventUtils.emitMultichainTransferIn(eventEmitter, token, account, amount, srcChainId);\n }\n\n /**\n * @dev transfer the specified amount of tokens from user's multichain balance to receiver\n * @param token the token to transfer\n * @param account the account for which the multichain balance is decreased\n * @param receiver the account to transfer to\n * @param amount the amount of tokens to transfer\n * @param srcChainId the source chain id\n */\n function transferOut(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n address token,\n address account,\n address receiver,\n uint256 amount,\n uint256 srcChainId\n ) external {\n if (amount == 0) {\n return;\n }\n\n uint256 balance = getMultichainBalanceAmount(dataStore, account, token);\n if (balance < amount) {\n revert Errors.InsufficientMultichainBalance(account, token, balance, amount);\n }\n\n dataStore.decrementUint(Keys.multichainBalanceKey(account, token), amount);\n multichainVault.transferOut(token, receiver, amount);\n MultichainEventUtils.emitMultichainTransferOut(eventEmitter, token, account, receiver, amount, srcChainId);\n }\n\n function getMultichainBalanceAmount(\n DataStore dataStore,\n address account,\n address token\n ) public view returns (uint256) {\n return dataStore.getUint(Keys.multichainBalanceKey(account, token));\n }\n\n function validateMultichainProvider(DataStore dataStore, address provider) external view {\n bytes32 providerKey = Keys.isMultichainProviderEnabledKey(provider);\n if (!dataStore.getBool(providerKey)) {\n revert Errors.InvalidMultichainProvider(provider);\n }\n }\n\n function validateMultichainEndpoint(DataStore dataStore, address endpoint) external view {\n bytes32 endpointKey = Keys.isMultichainEndpointEnabledKey(endpoint);\n if (!dataStore.getBool(endpointKey)) {\n revert Errors.InvalidMultichainEndpoint(endpoint);\n }\n }\n}\n" + }, + "contracts/multichain/MultichainVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/StrictBank.sol\";\n\n/**\n * @title MultichainVault\n * @dev Vault for crosschain deposits\n */\ncontract MultichainVault is StrictBank {\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\n}\n" + }, + "contracts/nonce/NonceUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\n\n// @title NonceUtils\n// @dev Library to keep track of an incrementing nonce value\nlibrary NonceUtils {\n // @dev get the current nonce value\n // @param dataStore DataStore\n function getCurrentNonce(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getUint(Keys.NONCE);\n }\n\n // @dev increment the current nonce value\n // @param dataStore DataStore\n // @return the new nonce value\n function incrementNonce(DataStore dataStore) internal returns (uint256) {\n return dataStore.incrementUint(Keys.NONCE, 1);\n }\n\n // @dev convenience function to create a bytes32 hash using the next nonce\n // it would be possible to use the nonce directly as an ID / key\n // however, for positions the key is a bytes32 value based on a hash of\n // the position values\n // so bytes32 is used instead for a standard key type\n // @param dataStore DataStore\n // @return bytes32 hash using the next nonce value\n function getNextKey(DataStore dataStore) internal returns (bytes32) {\n uint256 nonce = incrementNonce(dataStore);\n bytes32 key = getKey(dataStore, nonce);\n\n return key;\n }\n\n function getCurrentKey(DataStore dataStore) internal view returns (bytes32) {\n uint256 nonce = getCurrentNonce(dataStore);\n bytes32 key = getKey(dataStore, nonce);\n\n return key;\n }\n\n function getKey(DataStore dataStore, uint256 nonce) internal pure returns (bytes32) {\n return keccak256(abi.encode(address(dataStore), nonce));\n }\n}\n" + }, + "contracts/oracle/ChainlinkDataStreamProvider.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"./IOracleProvider.sol\";\nimport \"./IChainlinkDataStreamVerifier.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../chain/Chain.sol\";\n\ncontract ChainlinkDataStreamProvider is IOracleProvider {\n\n DataStore public immutable dataStore;\n address public immutable oracle;\n IChainlinkDataStreamVerifier public immutable verifier;\n\n // bid: min price, highest buy price\n // ask: max price, lowest sell price\n struct Report {\n bytes32 feedId; // The feed ID the report has data for\n uint32 validFromTimestamp; // Earliest timestamp for which price is applicable\n uint32 observationsTimestamp; // Latest timestamp for which price is applicable\n uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (WETH/ETH)\n uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK\n uint32 expiresAt; // Latest timestamp where the report can be verified onchain\n int192 price; // DON consensus median price, carried to 8 decimal places\n int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation\n int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation\n }\n\n modifier onlyOracle() {\n if (msg.sender != oracle) {\n revert Errors.Unauthorized(msg.sender, \"Oracle\");\n }\n _;\n }\n\n constructor(\n DataStore _dataStore,\n address _oracle,\n IChainlinkDataStreamVerifier _verifier\n ) {\n dataStore = _dataStore;\n oracle = _oracle;\n verifier = _verifier;\n }\n\n function shouldAdjustTimestamp() external pure returns (bool) {\n return true;\n }\n\n function isChainlinkOnChainProvider() external pure returns (bool) {\n return false;\n }\n\n function getOraclePrice(\n address token,\n bytes memory data\n ) external onlyOracle returns (OracleUtils.ValidatedPrice memory) {\n\n bytes32 feedId = dataStore.getBytes32(Keys.dataStreamIdKey(token));\n if (feedId == bytes32(0)) {\n revert Errors.EmptyDataStreamFeedId(token);\n }\n\n bytes memory payloadParameter = _getPayloadParameter();\n bytes memory verifierResponse = verifier.verify(data, payloadParameter);\n\n Report memory report = abi.decode(verifierResponse, (Report));\n\n if (feedId != report.feedId) {\n revert Errors.InvalidDataStreamFeedId(token, report.feedId, feedId);\n }\n\n if (report.bid <= 0 || report.ask <= 0) {\n revert Errors.InvalidDataStreamPrices(token, report.bid, report.ask);\n }\n\n if (report.bid > report.ask) {\n revert Errors.InvalidDataStreamBidAsk(token, report.bid, report.ask);\n }\n\n uint256 precision = _getDataStreamMultiplier(token);\n uint256 adjustedBidPrice = Precision.mulDiv(uint256(uint192(report.bid)), precision, Precision.FLOAT_PRECISION);\n uint256 adjustedAskPrice = Precision.mulDiv(uint256(uint192(report.ask)), precision, Precision.FLOAT_PRECISION);\n\n uint256 spreadReductionFactor = _getDataStreamSpreadReductionFactor(token);\n if (spreadReductionFactor != 0) {\n // small optimization for full reduction\n if (spreadReductionFactor == Precision.FLOAT_PRECISION) {\n adjustedBidPrice = (adjustedAskPrice + adjustedBidPrice) / 2;\n adjustedAskPrice = adjustedBidPrice;\n } else {\n uint256 halfSpread = (adjustedAskPrice - adjustedBidPrice) / 2;\n adjustedBidPrice = adjustedBidPrice + Precision.applyFactor(halfSpread, spreadReductionFactor);\n adjustedAskPrice = adjustedAskPrice - Precision.applyFactor(halfSpread, spreadReductionFactor);\n }\n }\n\n return OracleUtils.ValidatedPrice({\n token: token,\n min: adjustedBidPrice,\n max: adjustedAskPrice,\n timestamp: report.observationsTimestamp,\n provider: address(this)\n });\n }\n\n function _getDataStreamSpreadReductionFactor(address token) internal view returns (uint256) {\n uint256 spreadReductionFactor = dataStore.getUint(Keys.dataStreamSpreadReductionFactorKey(token));\n if (spreadReductionFactor > Precision.FLOAT_PRECISION) {\n revert Errors.InvalidDataStreamSpreadReductionFactor(token, spreadReductionFactor);\n }\n\n return spreadReductionFactor;\n }\n\n function _getDataStreamMultiplier(address token) internal view returns (uint256) {\n uint256 multiplier = dataStore.getUint(Keys.dataStreamMultiplierKey(token));\n\n if (multiplier == 0) {\n revert Errors.EmptyDataStreamMultiplier(token);\n }\n\n return multiplier;\n }\n\n function _getPayloadParameter() internal view returns (bytes memory) {\n // LINK token address\n address feeToken = dataStore.getAddress(Keys.CHAINLINK_PAYMENT_TOKEN);\n\n if (feeToken == address(0)) {\n return new bytes(0);\n }\n\n return abi.encode(feeToken);\n }\n}\n" + }, + "contracts/oracle/ChainlinkPriceFeedProvider.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"./IOracleProvider.sol\";\nimport \"./ChainlinkPriceFeedUtils.sol\";\n\ncontract ChainlinkPriceFeedProvider is IOracleProvider {\n DataStore public immutable dataStore;\n\n constructor(DataStore _dataStore) {\n dataStore = _dataStore;\n }\n\n function shouldAdjustTimestamp() external pure returns (bool) {\n return false;\n }\n\n function isChainlinkOnChainProvider() external pure returns (bool) {\n return true;\n }\n\n // @dev the timestamp returned is based on the current blockchain timestamp\n // this is because Chainlink on-chain price feeds have a lower update frequency\n // if a Chainlink on-chain price feed is used, it is assumed that the feed\n // is sufficiently updated for the intended usage\n //\n // if an on-chain Chainlink price is used together with other price feeds\n // and if the timestamp of the other price feeds are older, this could cause\n // a MaxTimestampRangeExceeded error\n // if this occurs, the MAX_TIMESTAMP_RANGE value may need to be increased\n function getOraclePrice(\n address token,\n bytes memory /* data */\n ) external view returns (OracleUtils.ValidatedPrice memory) {\n (bool hasPriceFeed, uint256 price) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\n\n if (!hasPriceFeed) {\n revert Errors.EmptyChainlinkPriceFeed(token);\n }\n\n uint256 stablePrice = dataStore.getUint(Keys.stablePriceKey(token));\n\n Price.Props memory priceProps;\n\n if (stablePrice > 0) {\n priceProps = Price.Props(\n price < stablePrice ? price : stablePrice,\n price < stablePrice ? stablePrice : price\n );\n } else {\n priceProps = Price.Props(\n price,\n price\n );\n }\n\n return OracleUtils.ValidatedPrice({\n token: token,\n min: priceProps.min,\n max: priceProps.max,\n timestamp: Chain.currentTimestamp(),\n provider: address(this)\n });\n }\n}\n" + }, + "contracts/oracle/ChainlinkPriceFeedUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../chain/Chain.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../utils/Precision.sol\";\n\nimport \"./IPriceFeed.sol\";\n\n// @title ChainlinkPriceFeedProviderUtils\n// @dev Library for Chainlink price feed\nlibrary ChainlinkPriceFeedUtils {\n // there is a small risk of stale pricing due to latency in price updates or if the chain is down\n // this is meant to be for temporary use until low latency price feeds are supported for all tokens\n function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {\n address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));\n if (priceFeedAddress == address(0)) {\n return (false, 0);\n }\n\n IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);\n\n (\n /* uint80 roundID */,\n int256 _price,\n /* uint256 startedAt */,\n uint256 timestamp,\n /* uint80 answeredInRound */\n ) = priceFeed.latestRoundData();\n\n if (_price <= 0) {\n revert Errors.InvalidFeedPrice(token, _price);\n }\n\n uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));\n if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {\n revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);\n }\n\n uint256 price = SafeCast.toUint256(_price);\n uint256 precision = getPriceFeedMultiplier(dataStore, token);\n\n uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);\n\n return (true, adjustedPrice);\n }\n\n // @dev get the multiplier value to convert the external price feed price to the price of 1 unit of the token\n // represented with 30 decimals\n // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of\n // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)\n // if the external price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8)\n // in this case the priceFeedMultiplier should be 10 ^ 46\n // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24)\n // formula for decimals for price feed multiplier: 60 - (external price feed decimals) - (token decimals)\n //\n // @param dataStore DataStore\n // @param token the token to get the price feed multiplier for\n // @return the price feed multipler\n function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {\n uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));\n\n if (multiplier == 0) {\n revert Errors.EmptyChainlinkPriceFeedMultiplier(token);\n }\n\n return multiplier;\n }\n}\n" + }, + "contracts/oracle/EdgeDataStreamProvider.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"./IOracleProvider.sol\";\nimport \"./IChainlinkDataStreamVerifier.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../chain/Chain.sol\";\nimport \"./EdgeDataStreamVerifier.sol\";\n\ncontract EdgeDataStreamProvider is IOracleProvider {\n\n DataStore public immutable dataStore;\n address public immutable oracle;\n EdgeDataStreamVerifier public immutable verifier;\n\n modifier onlyOracle() {\n if (msg.sender != oracle) {\n revert Errors.Unauthorized(msg.sender, \"Oracle\");\n }\n _;\n }\n\n constructor(\n DataStore _dataStore,\n address _oracle,\n EdgeDataStreamVerifier _verifier\n ) {\n dataStore = _dataStore;\n oracle = _oracle;\n verifier = _verifier;\n }\n\n function shouldAdjustTimestamp() external pure returns (bool) {\n return true;\n }\n\n function isChainlinkOnChainProvider() external pure returns (bool) {\n return false;\n }\n\n function getOraclePrice(\n address token,\n bytes memory data\n ) external view onlyOracle returns (OracleUtils.ValidatedPrice memory) {\n\n bytes32 feedId = dataStore.getBytes32(Keys.edgeDataStreamIdKey(token));\n if (feedId == bytes32(0)) {\n revert Errors.EmptyDataStreamFeedId(token);\n }\n\n EdgeDataStreamVerifier.Report memory report = verifier.verifyData(data);\n\n if (feedId != report.feedId) {\n revert Errors.InvalidDataStreamFeedId(token, report.feedId, feedId);\n }\n\n if (report.bid == 0 || report.ask == 0) {\n revert Errors.InvalidEdgeDataStreamBidAsk(token, report.bid, report.ask);\n }\n\n if (report.bid > report.ask) {\n revert Errors.InvalidEdgeDataStreamPrices(token, report.bid, report.ask);\n }\n\n // @dev converting edge price feed price to the price of the 1 unit of the token represented with 30 decimals\n // e.g. WETH has 18 decimals and price of 3000 USD per WETH.\n // So oracle price decimals should be 30 - 18 = 10 ^ 12\n // Note that report.expo is a negative value\n // With edge price being negative we get formula: edgePrice * 10 ^ (30 - 18 - 8)\n // dataStore decimals instead of token.decimals is used here because token can be synthetic\n uint256 tokenDecimals = dataStore.getUint(Keys.edgeDataStreamTokenDecimalsKey(token));\n int256 floatMultiplier = int256(30) - int256(tokenDecimals) + report.expo;\n if (floatMultiplier < 0) {\n revert Errors.InvalidEdgeDataStreamExpo(report.expo);\n }\n uint256 adjustedBidPrice = report.bid * 10 ** (uint256(floatMultiplier));\n uint256 adjustedAskPrice = report.ask * 10 ** (uint256(floatMultiplier));\n\n return OracleUtils.ValidatedPrice({\n token: token,\n min: adjustedBidPrice,\n max: adjustedAskPrice,\n timestamp: report.timestamp,\n provider: address(this)\n });\n }\n}\n" + }, + "contracts/oracle/EdgeDataStreamVerifier.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport {Errors} from \"../error/Errors.sol\";\nimport {Cast} from \"../utils/Cast.sol\";\nimport {ECDSA} from \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n\ncontract EdgeDataStreamVerifier {\n\n struct Report {\n bytes32 feedId;\n uint256 bid; // bid: min price, highest buy price\n uint256 ask; // ask: max price, lowest sell price\n uint32 timestamp;\n int32 expo; // precision of bid&ask (negative value)\n }\n\n address public immutable trustedSigner;\n\n /**\n * @dev Constructor to set the trusted signer address\n * @param _trustedSigner The address of the trusted signer\n */\n constructor(address _trustedSigner) {\n if (_trustedSigner == address(0)) {\n revert Errors.InvalidTrustedSignerAddress();\n }\n trustedSigner = _trustedSigner;\n }\n\n\n function verifyData(bytes calldata data) public view returns (Report memory) {\n (\n string memory feedId,\n uint192 price,\n uint32 roundId,\n uint32 timestamp,\n uint256 bid,\n uint256 ask,\n bytes memory signature,\n int32 expo\n ) = abi.decode(data, (string, uint192, uint32, uint32, uint256, uint256, bytes, int32));\n\n if (!verifySignature(\n feedId, price, roundId, timestamp, bid, ask, expo,\n signature)) {\n revert Errors.InvalidEdgeSigner();\n }\n return Report(\n keccak256(bytes(feedId)),\n bid,\n ask,\n timestamp,\n expo\n );\n }\n\n function verifySignature(\n string memory feedId,\n uint192 price,\n uint32 roundId,\n uint32 timestamp,\n uint256 bid,\n uint256 ask,\n int32 expo,\n bytes memory signature\n ) public view returns (bool) {\n return extractSigner(\n feedId,\n price,\n roundId,\n timestamp,\n bid,\n ask,\n expo,\n signature\n ) == trustedSigner;\n }\n\n /**\n * @dev Extracts address that signed price feed message\n * @param feedId The ID of the price feed (e.g., \"BTCUSD\")\n * @param price The price value\n * @param roundId The round ID\n * @param timestamp The timestamp of the observation\n * @param bid The best bid price\n * @param ask The best ask price\n * @param signature The signature to verify\n * @return True if the signature is valid, false otherwise\n */\n function extractSigner(\n string memory feedId,\n uint192 price,\n uint32 roundId,\n uint32 timestamp,\n uint256 bid,\n uint256 ask,\n int32 expo,\n bytes memory signature\n ) public pure returns (address) {\n // Recreate the message that was signed\n bytes32 messageHash;\n {\n messageHash = getMessageHash(\n keccak256(bytes(feedId)),\n Cast.uint192ToBytes(price),\n Cast.uint32ToBytes(roundId),\n Cast.uint32ToBytes(timestamp),\n Cast.uint256ToBytes(bid),\n Cast.uint256ToBytes(ask),\n Cast.int32ToBytes(- expo)\n );\n }\n\n (address recovered, ECDSA.RecoverError recoverError) = ECDSA.tryRecover(messageHash, signature);\n if (recoverError != ECDSA.RecoverError.NoError) {\n revert Errors.InvalidEdgeSignature(uint(recoverError));\n }\n\n return recovered;\n }\n\n /**\n * @dev Creates a hash of the serialized price data in the same format as server does\n */\n function getMessageHash(\n bytes32 feedId,\n bytes memory price,\n bytes memory roundId,\n bytes memory ts,\n bytes memory bid,\n bytes memory ask,\n bytes memory expo\n ) private pure returns (bytes32) {\n\n // split one abi.encodePacked call into two to avoid stack too deep error\n bytes memory message = abi.encodePacked(\n feedId,\n price,\n expo\n );\n message = abi.encodePacked(message,\n roundId,\n ts,\n bid,\n ask\n );\n\n return keccak256(message);\n }\n}\n" + }, + "contracts/oracle/GmOracleProvider.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../role/RoleModule.sol\";\n\nimport \"./OracleStore.sol\";\nimport \"./OracleUtils.sol\";\nimport \"../price/Price.sol\";\nimport \"./GmOracleUtils.sol\";\nimport \"./IOracleProvider.sol\";\n\nimport \"../chain/Chain.sol\";\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"../utils/Bits.sol\";\nimport \"../utils/Array.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../utils/Uint256Mask.sol\";\n\n// @title Oracle\n// @dev Contract to validate and store signed values\n// Some calculations e.g. calculating the size in tokens for a position\n// may not work with zero / negative prices\n// as a result, zero / negative prices are considered empty / invalid\n// A market may need to be manually settled in this case\ncontract GmOracleProvider is RoleModule, IOracleProvider {\n using Price for Price.Props;\n using Uint256Mask for Uint256Mask.Mask;\n\n uint256 public constant SIGNER_INDEX_LENGTH = 16;\n // subtract 1 as the first slot is used to store number of signers\n uint256 public constant MAX_SIGNERS = 256 / SIGNER_INDEX_LENGTH - 1;\n // signer indexes are recorded in a signerIndexFlags uint256 value to check for uniqueness\n uint256 public constant MAX_SIGNER_INDEX = 256;\n\n DataStore public immutable dataStore;\n OracleStore public immutable oracleStore;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n OracleStore _oracleStore\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n oracleStore = _oracleStore;\n }\n\n function shouldAdjustTimestamp() external pure returns (bool) {\n return true;\n }\n\n function isChainlinkOnChainProvider() external pure returns (bool) {\n return false;\n }\n\n // @dev Oracle prices are signed as a value together with a precision, this allows\n // prices to be compacted as uint32 values.\n //\n // The signed prices represent the price of one unit of the token using a value\n // with 30 decimals of precision.\n //\n // Representing the prices in this way allows for conversions between token amounts\n // and fiat values to be simplified, e.g. to calculate the fiat value of a given\n // number of tokens the calculation would just be: `token amount * oracle price`,\n // to calculate the token amount for a fiat value it would be: `fiat value / oracle price`.\n //\n // The trade-off of this simplicity in calculation is that tokens with a small USD\n // price and a lot of decimals may have precision issues it is also possible that\n // a token's price changes significantly and results in requiring higher precision.\n //\n // ## Example 1\n //\n // The price of ETH is 5000, and ETH has 18 decimals.\n //\n // The price of one unit of ETH is `5000 / (10 ^ 18), 5 * (10 ^ -15)`.\n //\n // To handle the decimals, multiply the value by `(10 ^ 30)`.\n //\n // Price would be stored as `5000 / (10 ^ 18) * (10 ^ 30) => 5000 * (10 ^ 12)`.\n //\n // For gas optimization, these prices are sent to the oracle in the form of a uint8\n // decimal multiplier value and uint32 price value.\n //\n // If the decimal multiplier value is set to 8, the uint32 value would be `5000 * (10 ^ 12) / (10 ^ 8) => 5000 * (10 ^ 4)`.\n //\n // With this config, ETH prices can have a maximum value of `(2 ^ 32) / (10 ^ 4) => 4,294,967,296 / (10 ^ 4) => 429,496.7296` with 4 decimals of precision.\n //\n // ## Example 2\n //\n // The price of BTC is 60,000, and BTC has 8 decimals.\n //\n // The price of one unit of BTC is `60,000 / (10 ^ 8), 6 * (10 ^ -4)`.\n //\n // Price would be stored as `60,000 / (10 ^ 8) * (10 ^ 30) => 6 * (10 ^ 26) => 60,000 * (10 ^ 22)`.\n //\n // BTC prices maximum value: `(2 ^ 32) / (10 ^ 2) => 4,294,967,296 / (10 ^ 2) => 42,949,672.96`.\n //\n // Decimals of precision: 2.\n //\n // ## Example 3\n //\n // The price of USDC is 1, and USDC has 6 decimals.\n //\n // The price of one unit of USDC is `1 / (10 ^ 6), 1 * (10 ^ -6)`.\n //\n // Price would be stored as `1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)`.\n //\n // USDC prices maximum value: `(2 ^ 64) / (10 ^ 6) => 4,294,967,296 / (10 ^ 6) => 4294.967296`.\n //\n // Decimals of precision: 6.\n //\n // ## Example 4\n //\n // The price of DG is 0.00000001, and DG has 18 decimals.\n //\n // The price of one unit of DG is `0.00000001 / (10 ^ 18), 1 * (10 ^ -26)`.\n //\n // Price would be stored as `1 * (10 ^ -26) * (10 ^ 30) => 1 * (10 ^ 3)`.\n //\n // DG prices maximum value: `(2 ^ 64) / (10 ^ 11) => 4,294,967,296 / (10 ^ 11) => 0.04294967296`.\n //\n // Decimals of precision: 11.\n //\n // ## Decimal Multiplier\n //\n // The formula to calculate what the decimal multiplier value should be set to:\n //\n // Decimals: 30 - (token decimals) - (number of decimals desired for precision)\n //\n // - ETH: 30 - 18 - 4 => 8\n // - BTC: 30 - 8 - 2 => 20\n // - USDC: 30 - 6 - 6 => 18\n // - DG: 30 - 18 - 11 => 1\n function getOraclePrice(\n address token,\n bytes memory data\n ) external view returns (OracleUtils.ValidatedPrice memory) {\n GmOracleUtils.Report memory report = abi.decode(data, (GmOracleUtils.Report));\n address[] memory signers = _getSigners(report.signerInfo);\n\n if (report.minOracleBlockNumber > report.maxOracleBlockNumber) {\n revert Errors.GmInvalidMinMaxBlockNumber(report.minOracleBlockNumber, report.maxOracleBlockNumber);\n }\n\n if (report.maxOracleBlockNumber >= Chain.currentBlockNumber()) {\n revert Errors.GmInvalidBlockNumber(report.maxOracleBlockNumber, Chain.currentBlockNumber());\n }\n\n bytes32 tokenOracleType = dataStore.getBytes32(Keys.oracleTypeKey(token));\n\n for (uint256 i = 0; i < signers.length; i++) {\n if (i == 0) { continue; }\n\n // validate that minPrices are sorted in ascending order\n if (report.minPrices[i - 1] > report.minPrices[i]) {\n revert Errors.GmMinPricesNotSorted(token, report.minPrices[i], report.minPrices[i - 1]);\n }\n\n // validate that maxPrices are sorted in ascending order\n if (report.maxPrices[i - 1] > report.maxPrices[i]) {\n revert Errors.GmMaxPricesNotSorted(token, report.maxPrices[i], report.maxPrices[i - 1]);\n }\n }\n\n bytes32 salt = _getSalt();\n\n for (uint256 i = 0; i < signers.length; i++) {\n uint256 minPrice = report.minPrices[i];\n uint256 maxPrice = report.maxPrices[i];\n\n if (minPrice > maxPrice) {\n revert Errors.InvalidGmSignerMinMaxPrice(minPrice, maxPrice);\n }\n\n GmOracleUtils.validateSigner(\n salt,\n report,\n token,\n minPrice,\n maxPrice,\n tokenOracleType,\n report.signatures[i],\n signers[i]\n );\n }\n\n uint256 medianMinPrice = Array.getMedian(report.minPrices) * (10 ** report.precision);\n uint256 medianMaxPrice = Array.getMedian(report.maxPrices) * (10 ** report.precision);\n\n if (medianMinPrice == 0 || medianMaxPrice == 0) {\n revert Errors.InvalidGmOraclePrice(token);\n }\n\n if (medianMinPrice > medianMaxPrice) {\n revert Errors.InvalidGmMedianMinMaxPrice(medianMinPrice, medianMaxPrice);\n }\n\n return OracleUtils.ValidatedPrice({\n token: token,\n min: medianMinPrice,\n max: medianMaxPrice,\n timestamp: report.oracleTimestamp,\n provider: address(this)\n });\n }\n\n function _getSigners(\n uint256 signerInfo\n ) internal view returns (address[] memory) {\n // first 16 bits of signer info contains the number of signers\n address[] memory signers = new address[](signerInfo & Bits.BITMASK_16);\n\n if (signers.length < dataStore.getUint(Keys.MIN_ORACLE_SIGNERS)) {\n revert Errors.GmMinOracleSigners(signers.length, dataStore.getUint(Keys.MIN_ORACLE_SIGNERS));\n }\n\n if (signers.length > MAX_SIGNERS) {\n revert Errors.GmMaxOracleSigners(signers.length, MAX_SIGNERS);\n }\n\n Uint256Mask.Mask memory signerIndexMask;\n\n for (uint256 i; i < signers.length; i++) {\n uint256 signerIndex = signerInfo >> (16 + 16 * i) & Bits.BITMASK_16;\n\n if (signerIndex >= MAX_SIGNER_INDEX) {\n revert Errors.GmMaxSignerIndex(signerIndex, MAX_SIGNER_INDEX);\n }\n\n signerIndexMask.validateUniqueAndSetIndex(signerIndex, \"signerIndex\");\n\n signers[i] = oracleStore.getSigner(signerIndex);\n\n if (signers[i] == address(0)) {\n revert Errors.GmEmptySigner(signerIndex);\n }\n }\n\n return signers;\n }\n\n // it might be possible for the block.chainid to change due to a fork or similar\n // for this reason, this salt is not cached\n function _getSalt() internal view returns (bytes32) {\n return keccak256(abi.encode(block.chainid, \"xget-oracle-v1\"));\n }\n}\n" + }, + "contracts/oracle/GmOracleUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../error/Errors.sol\";\n\n// @title GmOracleUtils\n// @dev Library for GmOracle functions\nlibrary GmOracleUtils {\n struct Report {\n address token;\n uint256 signerInfo;\n uint256 precision;\n uint256 minOracleBlockNumber;\n uint256 maxOracleBlockNumber;\n uint256 oracleTimestamp;\n bytes32 blockHash;\n uint256[] minPrices;\n uint256[] maxPrices;\n bytes[] signatures;\n }\n\n // @dev validate the signer of a price\n // before calling this function, the expectedSigner should be validated to\n // ensure that it is not the zero address\n // @param report the oracle Report data\n // @param token the token used for the signed message hash\n // @param minPrice the min price used for the signed message hash\n // @param maxPrice the max price used for the signed message hash\n // @param tokenOracleType the token oracle type used for the signed message hash\n // @param signature the signer's signature\n // @param expectedSigner the address of the expected signer\n function validateSigner(\n bytes32 salt,\n Report memory report,\n address token,\n uint256 minPrice,\n uint256 maxPrice,\n bytes32 tokenOracleType,\n bytes memory signature,\n address expectedSigner\n ) internal pure {\n bytes32 digest = ECDSA.toEthSignedMessageHash(\n keccak256(abi.encode(\n salt,\n report.minOracleBlockNumber,\n report.maxOracleBlockNumber,\n report.oracleTimestamp,\n report.blockHash,\n token,\n tokenOracleType,\n 10 ** report.precision,\n minPrice,\n maxPrice\n ))\n );\n\n address recoveredSigner = ECDSA.recover(digest, signature);\n if (recoveredSigner != expectedSigner) {\n revert Errors.InvalidGmSignature(recoveredSigner, expectedSigner);\n }\n }\n}\n" + }, + "contracts/oracle/IChainlinkDataStreamVerifier.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IChainlinkDataStreamVerifier {\n /**\n * @notice Verifies that the data encoded has been signed\n * correctly by routing to the correct verifier, and bills the user if applicable.\n * @param payload The encoded data to be verified, including the signed\n * report.\n * @param parameterPayload fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address\n * @return verifierResponse The encoded report from the verifier.\n */\n function verify(\n bytes calldata payload,\n bytes calldata parameterPayload\n ) external payable returns (bytes memory verifierResponse);\n}\n" + }, + "contracts/oracle/IOracle.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"./OracleUtils.sol\";\n\ninterface IOracle {\n function minTimestamp() external view returns (uint256);\n function maxTimestamp() external view returns (uint256);\n function dataStore() external view returns (DataStore);\n function eventEmitter() external view returns (EventEmitter);\n\n function validateSequencerUp() external view;\n function setPrices(OracleUtils.SetPricesParams memory params) external;\n function setPricesForAtomicAction(OracleUtils.SetPricesParams memory params) external;\n function setPrimaryPrice(address token, Price.Props memory price) external;\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external;\n function clearAllPrices() external;\n function getTokensWithPricesCount() external view returns (uint256);\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory);\n function getPrimaryPrice(address token) external view returns (Price.Props memory);\n function validatePrices(\n OracleUtils.SetPricesParams memory params,\n bool forAtomicAction\n ) external returns (OracleUtils.ValidatedPrice[] memory);\n}\n" + }, + "contracts/oracle/IOracleProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./OracleUtils.sol\";\n\n// @title IOracleProvider\n// @dev Interface for an oracle provider\ninterface IOracleProvider {\n function getOraclePrice(\n address token,\n bytes memory data\n ) external returns (OracleUtils.ValidatedPrice memory);\n\n /// @dev for all oracle providers besides ChainlinkPriceFeedProvider\n function shouldAdjustTimestamp() external pure returns (bool);\n\n /// @dev for ChainlinkPriceFeedProvider\n function isChainlinkOnChainProvider() external pure returns (bool);\n}\n" + }, + "contracts/oracle/IPriceFeed.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n// @title IPriceFeed\n// @dev Interface for a price feed\ninterface IPriceFeed {\n function latestRoundData() external view returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function description() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/oracle/Oracle.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport { AggregatorV2V3Interface } from \"@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol\";\n\nimport \"../role/RoleModule.sol\";\n\nimport \"./OracleUtils.sol\";\nimport \"./IOracle.sol\";\nimport \"./IOracleProvider.sol\";\nimport \"./ChainlinkPriceFeedUtils.sol\";\nimport \"../price/Price.sol\";\n\nimport \"../chain/Chain.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\n\nimport \"../utils/Precision.sol\";\nimport \"../utils/Cast.sol\";\nimport \"../utils/Uint256Mask.sol\";\n\n// @title Oracle\n// @dev Contract to validate and store signed values\n// Some calculations e.g. calculating the size in tokens for a position\n// may not work with zero / negative prices\n// as a result, zero / negative prices are considered empty / invalid\n// A market may need to be manually settled in this case\ncontract Oracle is IOracle, RoleModule {\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableValues for EnumerableSet.AddressSet;\n using Price for Price.Props;\n using Uint256Mask for Uint256Mask.Mask;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n AggregatorV2V3Interface public immutable sequencerUptimeFeed;\n\n // tokensWithPrices stores the tokens with prices that have been set\n // this is used in clearAllPrices to help ensure that all token prices\n // set in setPrices are cleared after use\n EnumerableSet.AddressSet internal tokensWithPrices;\n mapping(address => Price.Props) public primaryPrices;\n\n uint256 public minTimestamp;\n uint256 public maxTimestamp;\n\n constructor(\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n AggregatorV2V3Interface _sequencerUptimeFeed\n ) RoleModule(_roleStore) {\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n sequencerUptimeFeed = _sequencerUptimeFeed;\n }\n\n // this can be used to help ensure that on-chain prices are updated\n // before actions dependent on those on-chain prices are allowed\n // additionally, this can also be used to provide a grace period for\n // users to top up collateral before liquidations occur\n function validateSequencerUp() public view {\n if (address(sequencerUptimeFeed) == address(0)) {\n return;\n }\n\n (\n /*uint80 roundID*/,\n int256 answer,\n uint256 startedAt,\n /*uint256 updatedAt*/,\n /*uint80 answeredInRound*/\n ) = sequencerUptimeFeed.latestRoundData();\n\n // answer == 0: sequencer is up\n // answer == 1: sequencer is down\n bool isSequencerUp = answer == 0;\n if (!isSequencerUp) {\n revert Errors.SequencerDown();\n }\n\n uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);\n\n // ensure the grace duration has passed after the\n // sequencer is back up.\n uint256 timeSinceUp = block.timestamp - startedAt;\n if (timeSinceUp <= sequencerGraceDuration) {\n revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);\n }\n }\n\n function setPrices(\n OracleUtils.SetPricesParams memory params\n ) external onlyController {\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);\n\n _setPrices(prices);\n }\n\n function setPricesForAtomicAction(\n OracleUtils.SetPricesParams memory params\n ) external onlyController {\n validateSequencerUp();\n\n OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);\n\n _setPrices(prices);\n }\n\n // @dev set the primary price\n // @param token the token to set the price for\n // @param price the price value to set to\n function setPrimaryPrice(address token, Price.Props memory price) external onlyController {\n _setPrimaryPrice(token, price);\n }\n\n function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {\n minTimestamp = _minTimestamp;\n maxTimestamp = _maxTimestamp;\n }\n\n // @dev clear all prices\n function clearAllPrices() external onlyController {\n uint256 length = tokensWithPrices.length();\n for (uint256 i; i < length; i++) {\n address token = tokensWithPrices.at(0);\n _removePrimaryPrice(token);\n }\n\n minTimestamp = 0;\n maxTimestamp = 0;\n }\n\n // @dev get the length of tokensWithPrices\n // @return the length of tokensWithPrices\n function getTokensWithPricesCount() external view returns (uint256) {\n return tokensWithPrices.length();\n }\n\n // @dev get the tokens of tokensWithPrices for the specified indexes\n // @param start the start index, the value for this index will be included\n // @param end the end index, the value for this index will not be included\n // @return the tokens of tokensWithPrices for the specified indexes\n function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {\n return tokensWithPrices.valuesAt(start, end);\n }\n\n // @dev get the primary price of a token\n // @param token the token to get the price for\n // @return the primary price of a token\n function getPrimaryPrice(address token) external view returns (Price.Props memory) {\n if (token == address(0)) { return Price.Props(0, 0); }\n\n Price.Props memory price = primaryPrices[token];\n if (price.isEmpty()) {\n revert Errors.EmptyPrimaryPrice(token);\n }\n\n return price;\n }\n\n function validatePrices(\n OracleUtils.SetPricesParams memory params,\n bool forAtomicAction\n ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {\n return _validatePrices(params, forAtomicAction);\n }\n\n // @dev validate and set prices\n // @param params OracleUtils.SetPricesParams\n function _setPrices(\n OracleUtils.ValidatedPrice[] memory prices\n ) internal {\n // in case of gasless relay the prices are not required if there is no need to swap fee tokens\n if (prices.length == 0) {\n return;\n }\n\n if (tokensWithPrices.length() != 0) {\n revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());\n }\n\n uint256 _minTimestamp = prices[0].timestamp;\n uint256 _maxTimestamp = prices[0].timestamp;\n\n for (uint256 i; i < prices.length; i++) {\n OracleUtils.ValidatedPrice memory validatedPrice = prices[i];\n\n _setPrimaryPrice(validatedPrice.token, Price.Props(\n validatedPrice.min,\n validatedPrice.max\n ));\n\n if (validatedPrice.timestamp < _minTimestamp) {\n _minTimestamp = validatedPrice.timestamp;\n }\n\n if (validatedPrice.timestamp > _maxTimestamp) {\n _maxTimestamp = validatedPrice.timestamp;\n }\n\n _emitOraclePriceUpdated(\n validatedPrice.token,\n validatedPrice.min,\n validatedPrice.max,\n validatedPrice.timestamp,\n validatedPrice.provider\n );\n }\n\n uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);\n if (_maxTimestamp - _minTimestamp > maxRange) {\n revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);\n }\n\n minTimestamp = _minTimestamp;\n maxTimestamp = _maxTimestamp;\n }\n\n function _validatePrices(\n OracleUtils.SetPricesParams memory params,\n bool forAtomicAction\n ) internal returns (OracleUtils.ValidatedPrice[] memory) {\n if (params.tokens.length != params.providers.length) {\n revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);\n }\n\n if (params.tokens.length != params.data.length) {\n revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);\n }\n\n OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);\n\n if (params.tokens.length == 0) {\n return prices;\n }\n\n uint256 maxPriceAge = forAtomicAction ? dataStore.getUint(Keys.MAX_ATOMIC_ORACLE_PRICE_AGE) : dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);\n uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);\n\n for (uint256 i; i < params.tokens.length; i++) {\n address _provider = params.providers[i];\n IOracleProvider provider = IOracleProvider(_provider);\n\n if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(_provider))) {\n revert Errors.InvalidOracleProvider(_provider);\n }\n\n address token = params.tokens[i];\n\n bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(_provider));\n\n // if the action is atomic then only validate that the provider is an\n // atomic provider\n // else, validate that the provider matches the oracleProviderForToken\n //\n // since for atomic actions, any atomic provider can be used, it is\n // recommended that only one atomic provider is configured per token\n // otherwise there is a risk that if there is a difference in pricing\n // between atomic oracle providers for a token, a user could use that\n // to gain a profit by alternating actions between the two atomic\n // providers\n if (forAtomicAction) {\n if (!isAtomicProvider) {\n revert Errors.NonAtomicOracleProvider(_provider);\n }\n } else {\n address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(address(this), token));\n if (_provider != expectedProvider) {\n revert Errors.InvalidOracleProviderForToken(_provider, expectedProvider);\n }\n }\n\n bytes memory data = params.data[i];\n\n OracleUtils.ValidatedPrice memory validatedPrice = provider.getOraclePrice(\n token,\n data\n );\n\n // for atomic providers, the timestamp will be the current block's timestamp\n // the timestamp should not be adjusted\n if (provider.shouldAdjustTimestamp()) {\n uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(_provider, token));\n validatedPrice.timestamp -= timestampAdjustment;\n }\n\n if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {\n revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());\n }\n\n if (!provider.isChainlinkOnChainProvider()) {\n (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);\n\n if (hasRefPrice) {\n _validateRefPrice(\n token,\n validatedPrice.min,\n refPrice,\n maxRefPriceDeviationFactor\n );\n\n _validateRefPrice(\n token,\n validatedPrice.max,\n refPrice,\n maxRefPriceDeviationFactor\n );\n }\n }\n\n prices[i] = validatedPrice;\n }\n\n return prices;\n }\n\n function _validateRefPrice(\n address token,\n uint256 price,\n uint256 refPrice,\n uint256 maxRefPriceDeviationFactor\n ) internal pure {\n uint256 diff = Calc.diff(price, refPrice);\n uint256 diffFactor = Precision.toFactor(diff, refPrice);\n\n if (diffFactor > maxRefPriceDeviationFactor) {\n revert Errors.MaxRefPriceDeviationExceeded(\n token,\n price,\n refPrice,\n maxRefPriceDeviationFactor\n );\n }\n }\n\n function _setPrimaryPrice(address token, Price.Props memory price) internal {\n if (price.min > price.max) {\n revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);\n }\n\n Price.Props memory existingPrice = primaryPrices[token];\n\n if (!existingPrice.isEmpty()) {\n revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);\n }\n\n primaryPrices[token] = price;\n tokensWithPrices.add(token);\n }\n\n function _removePrimaryPrice(address token) internal {\n delete primaryPrices[token];\n tokensWithPrices.remove(token);\n }\n\n function _emitOraclePriceUpdated(\n address token,\n uint256 minPrice,\n uint256 maxPrice,\n uint256 timestamp,\n address provider\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"token\", token);\n eventData.addressItems.setItem(1, \"provider\", provider);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"minPrice\", minPrice);\n eventData.uintItems.setItem(1, \"maxPrice\", maxPrice);\n eventData.uintItems.setItem(2, \"timestamp\", timestamp);\n\n eventEmitter.emitEventLog1(\n \"OraclePriceUpdate\",\n Cast.toBytes32(token),\n eventData\n );\n }\n}\n" + }, + "contracts/oracle/OracleModule.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./IOracle.sol\";\n\n// @title OracleModule\n// @dev Provides convenience functions for interacting with the Oracle\ncontract OracleModule {\n IOracle public immutable oracle;\n\n constructor(IOracle _oracle) {\n oracle = _oracle;\n }\n\n // @dev sets oracle prices, perform any additional tasks required,\n // and clear the oracle prices after\n //\n // care should be taken to avoid re-entrancy while using this call\n // since re-entrancy could allow functions to be called with prices\n // meant for a different type of transaction\n // the tokensWithPrices.length check in oracle.setPrices should help\n // mitigate this\n //\n // @param params OracleUtils.SetPricesParams\n modifier withOraclePrices(\n OracleUtils.SetPricesParams memory params\n ) {\n oracle.setPrices(params);\n _;\n oracle.clearAllPrices();\n }\n\n modifier withOraclePricesForAtomicAction(\n OracleUtils.SetPricesParams memory params\n ) {\n oracle.setPricesForAtomicAction(params);\n _;\n oracle.clearAllPrices();\n }\n\n // @dev set oracle prices for a simulation\n // tokensWithPrices is not set in this function\n // it is possible for withSimulatedOraclePrices to be called and a function\n // using withOraclePrices to be called after\n // or for a function using withOraclePrices to be called and withSimulatedOraclePrices\n // called after\n // this should not cause an issue because this transaction should always revert\n // and any state changes based on simulated prices as well as the setting of simulated\n // prices should not be persisted\n // @param params OracleUtils.SimulatePricesParams\n modifier withSimulatedOraclePrices(\n OracleUtils.SimulatePricesParams memory params\n ) {\n if (params.primaryTokens.length != params.primaryPrices.length) {\n revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);\n }\n\n for (uint256 i; i < params.primaryTokens.length; i++) {\n address token = params.primaryTokens[i];\n Price.Props memory price = params.primaryPrices[i];\n oracle.setPrimaryPrice(token, price);\n }\n\n oracle.setTimestamps(params.minTimestamp, params.maxTimestamp);\n\n _;\n\n revert Errors.EndOfOracleSimulation();\n }\n}\n" + }, + "contracts/oracle/OracleStore.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../role/RoleModule.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\n// @title OracleStore\n// @dev Stores the list of oracle signers\ncontract OracleStore is RoleModule {\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableValues for EnumerableSet.AddressSet;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n EventEmitter public immutable eventEmitter;\n\n EnumerableSet.AddressSet internal signers;\n\n constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {\n eventEmitter = _eventEmitter;\n }\n\n // @dev adds a signer\n // @param account address of the signer to add\n function addSigner(address account) external onlyController {\n signers.add(account);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventEmitter.emitEventLog1(\n \"SignerAdded\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n // @dev removes a signer\n // @param account address of the signer to remove\n function removeSigner(address account) external onlyController {\n signers.remove(account);\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventEmitter.emitEventLog1(\n \"SignerRemoved\",\n Cast.toBytes32(account),\n eventData\n );\n }\n\n // @dev get the total number of signers\n // @return the total number of signers\n function getSignerCount() external view returns (uint256) {\n return signers.length();\n }\n\n // @dev get the signer at the specified index\n // @param index the index of the signer to get\n // @return the signer at the specified index\n function getSigner(uint256 index) external view returns (address) {\n return signers.at(index);\n }\n\n // @dev get the signers for the specified indexes\n // @param start the start index, the value for this index will be included\n // @param end the end index, the value for this index will not be included\n // @return the signers for the specified indexes\n function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {\n return signers.valuesAt(start, end);\n }\n}\n" + }, + "contracts/oracle/OracleUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Array.sol\";\nimport \"../price/Price.sol\";\n\n// @title OracleUtils\n// @dev Library for oracle functions\nlibrary OracleUtils {\n using Array for uint256[];\n\n struct SetPricesParams {\n address[] tokens;\n address[] providers;\n bytes[] data;\n }\n\n struct ValidatedPrice {\n address token;\n uint256 min;\n uint256 max;\n uint256 timestamp;\n address provider;\n }\n\n struct SimulatePricesParams {\n address[] primaryTokens;\n Price.Props[] primaryPrices;\n uint256 minTimestamp;\n uint256 maxTimestamp;\n }\n\n function isOracleError(bytes4 errorSelector) internal pure returns (bool) {\n if (isOracleTimestampError(errorSelector)) {\n return true;\n }\n\n if (isEmptyPriceError(errorSelector)) {\n return true;\n }\n\n return false;\n }\n\n function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {\n if (errorSelector == Errors.EmptyPrimaryPrice.selector) {\n return true;\n }\n\n return false;\n }\n\n function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {\n if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {\n return true;\n }\n\n if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {\n return true;\n }\n\n return false;\n }\n}\n" + }, + "contracts/order/AutoCancelUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../error/Errors.sol\";\n\nlibrary AutoCancelUtils {\n function addAutoCancelOrderKey(DataStore dataStore, bytes32 positionKey, bytes32 orderKey) internal {\n bytes32 listKey = Keys.autoCancelOrderListKey(positionKey);\n dataStore.addBytes32(listKey, orderKey);\n\n uint256 maxAutoCancelOrders = getMaxAutoCancelOrders(dataStore);\n uint256 count = dataStore.getBytes32Count(listKey);\n if (count > maxAutoCancelOrders) {\n revert Errors.MaxAutoCancelOrdersExceeded(count, maxAutoCancelOrders);\n }\n }\n\n function removeAutoCancelOrderKey(DataStore dataStore, bytes32 positionKey, bytes32 orderKey) internal {\n bytes32 listKey = Keys.autoCancelOrderListKey(positionKey);\n dataStore.removeBytes32(listKey, orderKey);\n }\n\n function getAutoCancelOrderKeys(DataStore dataStore, bytes32 positionKey) internal view returns (bytes32[] memory) {\n bytes32 listKey = Keys.autoCancelOrderListKey(positionKey);\n uint256 maxAutoCancelOrders = getMaxAutoCancelOrders(dataStore);\n return dataStore.getBytes32ValuesAt(listKey, 0, maxAutoCancelOrders);\n }\n\n function getMaxAutoCancelOrders(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getUint(Keys.MAX_AUTO_CANCEL_ORDERS);\n }\n}\n" + }, + "contracts/order/BaseOrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./Order.sol\";\nimport \"../market/Market.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../referral/IReferralStorage.sol\";\n\nimport \"../order/OrderVault.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../position/Position.sol\";\n\nimport \"../oracle/IOracle.sol\";\nimport \"../swap/ISwapHandler.sol\";\n\nimport \"../multichain/MultichainVault.sol\";\n\n// @title Order\n// @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils\n// DecreaseOrderUtils, SwapOrderUtils\nlibrary BaseOrderUtils {\n using SafeCast for int256;\n using SafeCast for uint256;\n\n using Order for Order.Props;\n using Price for Price.Props;\n\n // @dev ExecuteOrderParams struct used in executeOrder to avoid stack\n // too deep errors\n //\n // @param contracts ExecuteOrderParamsContracts\n // @param key the key of the order to execute\n // @param order the order to execute\n // @param swapPathMarkets the market values of the markets in the swapPath\n // @param minOracleTimestamp the min oracle timestamp\n // @param maxOracleTimestamp the max oracle timestamp\n // @param market market values of the trading market\n // @param keeper the keeper sending the transaction\n // @param startingGas the starting gas\n // @param secondaryOrderType the secondary order type\n struct ExecuteOrderParams {\n ExecuteOrderParamsContracts contracts;\n bytes32 key;\n Order.Props order;\n Market.Props[] swapPathMarkets;\n uint256 minOracleTimestamp;\n uint256 maxOracleTimestamp;\n Market.Props market;\n address keeper;\n uint256 startingGas;\n Order.SecondaryOrderType secondaryOrderType;\n }\n\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param orderVault OrderVault\n // @param oracle Oracle\n // @param swapHandler ISwapHandler\n // @param referralStorage IReferralStorage\n struct ExecuteOrderParamsContracts {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n OrderVault orderVault;\n IOracle oracle;\n ISwapHandler swapHandler;\n IReferralStorage referralStorage;\n }\n\n struct GetExecutionPriceCache {\n uint256 price;\n uint256 executionPrice;\n int256 adjustedPriceImpactUsd;\n }\n\n // @dev validate the price for increase / decrease orders based on the triggerPrice\n // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice\n //\n // it is possible to update the oracle to support a primaryPrice and a secondaryPrice\n // which would allow for stop-loss orders to be executed at exactly the triggerPrice\n //\n // however, this may lead to gaming issues, an example:\n // - the current price is $2020\n // - a user has a long position and creates a stop-loss decrease order for < $2010\n // - if the order has a swap from ETH to USDC and the user is able to cause the order\n // to be frozen / unexecutable by manipulating state or otherwise\n // - then if price decreases to $2000, and the user is able to manipulate state such that\n // the order becomes executable with $2010 being used as the price instead\n // - then the user would be able to perform the swap at a higher price than should possible\n //\n // additionally, using the exact order's triggerPrice could lead to gaming issues during times\n // of volatility due to users setting tight stop-losses to minimize loss while betting on a\n // directional price movement, fees and price impact should help a bit with this, but there\n // still may be some probability of success\n //\n // the order keepers can use the closest oracle price to the triggerPrice for execution, which\n // should lead to similar order execution prices with reduced gaming risks\n //\n // if an order is frozen, the frozen order keepers should use the most recent price for order\n // execution instead\n //\n // @param oracle Oracle\n // @param indexToken the index token\n // @param orderType the order type\n // @param triggerPrice the order's triggerPrice\n // @param isLong whether the order is for a long or short\n function validateOrderTriggerPrice(\n IOracle oracle,\n address indexToken,\n Order.OrderType orderType,\n uint256 triggerPrice,\n bool isLong\n ) internal view {\n if (\n Order.isSwapOrder(orderType) ||\n Order.isMarketOrder(orderType) ||\n Order.isLiquidationOrder(orderType)\n ) {\n return;\n }\n\n Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);\n\n // for limit increase long positions:\n // - the order should be executed when the oracle price is <= triggerPrice\n // - primaryPrice.max should be used for the oracle price\n // for limit increase short positions:\n // - the order should be executed when the oracle price is >= triggerPrice\n // - primaryPrice.min should be used for the oracle price\n if (orderType == Order.OrderType.LimitIncrease) {\n bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;\n\n if (!ok) {\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\n }\n\n return;\n }\n\n // for stop increase long positions:\n // - the order should be executed when the oracle price is >= triggerPrice\n // - primaryPrice.max should be used for the oracle price\n // for stop increase short positions:\n // - the order should be executed when the oracle price is <= triggerPrice\n // - primaryPrice.min should be used for the oracle price\n if (orderType == Order.OrderType.StopIncrease) {\n bool ok = isLong ? primaryPrice.max >= triggerPrice : primaryPrice.min <= triggerPrice;\n\n if (!ok) {\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\n }\n\n return;\n }\n\n // for limit decrease long positions:\n // - the order should be executed when the oracle price is >= triggerPrice\n // - primaryPrice.min should be used for the oracle price\n // for limit decrease short positions:\n // - the order should be executed when the oracle price is <= triggerPrice\n // - primaryPrice.max should be used for the oracle price\n if (orderType == Order.OrderType.LimitDecrease) {\n bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;\n\n if (!ok) {\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\n }\n\n return;\n }\n\n // for stop-loss decrease long positions:\n // - the order should be executed when the oracle price is <= triggerPrice\n // - primaryPrice.min should be used for the oracle price\n // for stop-loss decrease short positions:\n // - the order should be executed when the oracle price is >= triggerPrice\n // - primaryPrice.max should be used for the oracle price\n if (orderType == Order.OrderType.StopLossDecrease) {\n bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;\n\n if (!ok) {\n revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));\n }\n\n return;\n }\n\n revert Errors.UnsupportedOrderType(uint256(orderType));\n }\n\n function validateOrderValidFromTime(\n Order.OrderType orderType,\n uint256 validFromTime\n ) internal view {\n if (Order.isMarketOrder(orderType)) {\n return;\n }\n\n uint256 currentTimestamp = Chain.currentTimestamp();\n if (validFromTime > currentTimestamp) {\n revert Errors.OrderValidFromTimeNotReached(validFromTime, currentTimestamp);\n }\n }\n\n function getExecutionPriceForIncrease(\n uint256 sizeDeltaUsd,\n uint256 sizeDeltaInTokens,\n uint256 acceptablePrice,\n bool isLong\n ) internal pure returns (uint256) {\n if (sizeDeltaInTokens == 0) {\n revert Errors.EmptySizeDeltaInTokens();\n }\n\n uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;\n\n // increase order:\n // - long: executionPrice should be smaller than acceptablePrice\n // - short: executionPrice should be larger than acceptablePrice\n if (\n (isLong && executionPrice <= acceptablePrice) ||\n (!isLong && executionPrice >= acceptablePrice)\n ) {\n return executionPrice;\n }\n\n // the validateOrderTriggerPrice function should have validated if the price fulfills\n // the order's trigger price\n //\n // for increase orders, the negative price impact is not capped\n //\n // for both increase and decrease orders, if it is due to price impact that the\n // order cannot be fulfilled then the order should be frozen\n //\n // this is to prevent gaming by manipulation of the price impact value\n //\n // usually it should be costly to game the price impact value\n // however, for certain cases, e.g. a user already has a large position opened\n // the user may create limit orders that would only trigger after they close\n // their position, this gives the user the option to cancel the pending order if\n // prices do not move in their favour or to close their position and let the order\n // execute if prices move in their favour\n //\n // it may also be possible for users to prevent the execution of orders from other users\n // by manipulating the price impact, though this should be costly\n revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);\n }\n\n function getExecutionPriceForDecrease(\n Price.Props memory indexTokenPrice,\n uint256 positionSizeInUsd,\n uint256 positionSizeInTokens,\n uint256 sizeDeltaUsd,\n int256 priceImpactUsd,\n uint256 acceptablePrice,\n bool isLong\n ) internal pure returns (uint256) {\n // Only the maximum impact factor is applied to cap the resulting priceImpactUsd here.\n // This does NOT include capping based on the price impact pool balance, so the computed\n // executionPrice may not reflect the actual executionPrice experienced by the order.\n // Consumers of this function should be aware that the final execution price may differ\n // if further capping is applied elsewhere based on the impact pool.\n GetExecutionPriceCache memory cache;\n\n // decrease order:\n // - long: use the smaller price\n // - short: use the larger price\n cache.price = indexTokenPrice.pickPrice(!isLong);\n cache.executionPrice = cache.price;\n\n // using closing of long positions as an example\n // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens\n // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd\n // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens\n // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)\n // priceImpactUsd should adjust the execution price such that:\n // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -\n // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd\n //\n // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)\n // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)\n // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\n //\n // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\n // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd\n // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)\n // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)\n // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd\n //\n // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5\n // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600\n // realizedPnl based on price, without price impact: 0\n // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000\n\n // a positive adjustedPriceImpactUsd would decrease the executionPrice\n // a negative adjustedPriceImpactUsd would increase the executionPrice\n\n // for increase orders, the adjustedPriceImpactUsd is added to the divisor\n // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice\n // increase long order:\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice\n // increase short order:\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice\n\n // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator\n // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice\n // decrease long order:\n // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice\n // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\n // decrease short order:\n // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice\n // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice\n // adjust price by price impact\n if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {\n cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;\n\n if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {\n revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);\n }\n\n int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();\n int256 _executionPrice = cache.price.toInt256() + adjustment;\n\n if (_executionPrice < 0) {\n revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);\n }\n\n cache.executionPrice = _executionPrice.toUint256();\n }\n\n // decrease order:\n // - long: executionPrice should be larger than acceptablePrice\n // - short: executionPrice should be smaller than acceptablePrice\n if (\n (isLong && cache.executionPrice >= acceptablePrice) ||\n (!isLong && cache.executionPrice <= acceptablePrice)\n ) {\n return cache.executionPrice;\n }\n\n // the validateOrderTriggerPrice function should have validated if the price fulfills\n // the order's trigger price\n //\n // for decrease orders, the price impact should already be capped, so if the user\n // had set an acceptable price within the range of the capped price impact, then\n // the order should be fulfillable at the acceptable price\n //\n // for increase orders, the negative price impact is not capped\n //\n // for both increase and decrease orders, if it is due to price impact that the\n // order cannot be fulfilled then the order should be frozen\n //\n // this is to prevent gaming by manipulation of the price impact value\n //\n // usually it should be costly to game the price impact value\n // however, for certain cases, e.g. a user already has a large position opened\n // the user may create limit orders that would only trigger after they close\n // their position, this gives the user the option to cancel the pending order if\n // prices do not move in their favour or to close their position and let the order\n // execute if prices move in their favour\n //\n // it may also be possible for users to prevent the execution of orders from other users\n // by manipulating the price impact, though this should be costly\n revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);\n }\n\n // @dev validate that an order exists\n // @param order the order to check\n function validateNonEmptyOrder(Order.Props memory order) internal pure {\n if (order.account() == address(0)) {\n revert Errors.EmptyOrder();\n }\n\n if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {\n revert Errors.EmptyOrder();\n }\n }\n\n function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {\n if (Order.isDecreaseOrder(order.orderType())) {\n return Position.getPositionKey(\n order.account(),\n order.market(),\n order.initialCollateralToken(),\n order.isLong()\n );\n }\n\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\n }\n}\n" + }, + "contracts/order/DecreaseOrderExecutor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../exchange/IOrderExecutor.sol\";\nimport \"./DecreaseOrderUtils.sol\";\n\ncontract DecreaseOrderExecutor is ReentrancyGuard, RoleModule {\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) external nonReentrant onlyController returns (EventUtils.EventLogData memory) {\n return DecreaseOrderUtils.processOrder(params);\n }\n}\n" + }, + "contracts/order/DecreaseOrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseOrderUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\nimport \"../position/DecreasePositionUtils.sol\";\nimport \"../error/ErrorUtils.sol\";\nimport \"../multichain/MultichainUtils.sol\";\n\n// @title DecreaseOrderUtils\n// @dev Library for functions to help with processing a decrease order\n// note that any updates to the eventData\nlibrary DecreaseOrderUtils {\n using Position for Position.Props;\n using Order for Order.Props;\n using Array for uint256[];\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // @dev process a decrease order\n // @param params BaseOrderUtils.ExecuteOrderParams\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {\n Order.Props memory order = params.order;\n MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market);\n\n bytes32 positionKey = Position.getPositionKey(order.account(), order.market(), order.initialCollateralToken(), order.isLong());\n Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey);\n PositionUtils.validateNonEmptyPosition(position);\n\n validateOracleTimestamp(\n params.contracts.dataStore,\n order.orderType(),\n order.updatedAtTime(),\n order.validFromTime(),\n position.increasedAtTime(),\n position.decreasedAtTime(),\n params.minOracleTimestamp,\n params.maxOracleTimestamp\n );\n\n DecreasePositionUtils.DecreasePositionResult memory result = DecreasePositionUtils.decreasePosition(\n PositionUtils.UpdatePositionParams(\n params.contracts,\n params.market,\n order,\n params.key,\n position,\n positionKey,\n params.secondaryOrderType\n )\n );\n\n // if the pnlToken and the collateralToken are different\n // and if a swap fails or no swap was requested\n // then it is possible to receive two separate tokens from decreasing\n // the position\n // transfer the two tokens to the user in this case and skip processing\n // the swapPath\n if (result.secondaryOutputAmount > 0) {\n _validateOutputAmount(\n params.contracts.oracle,\n result.outputToken,\n result.outputAmount,\n result.secondaryOutputToken,\n result.secondaryOutputAmount,\n order.minOutputAmount()\n );\n\n if (order.srcChainId() == 0) {\n MarketToken(payable(order.market())).transferOut(\n result.outputToken,\n order.receiver(),\n result.outputAmount,\n order.shouldUnwrapNativeToken()\n );\n\n MarketToken(payable(order.market())).transferOut(\n result.secondaryOutputToken,\n order.receiver(),\n result.secondaryOutputAmount,\n order.shouldUnwrapNativeToken()\n );\n } else {\n MarketToken(payable(order.market())).transferOut(\n result.outputToken,\n address(params.contracts.multichainVault), // receiver\n result.outputAmount,\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n result.outputToken,\n order.receiver(),\n order.srcChainId()\n );\n\n MarketToken(payable(order.market())).transferOut(\n result.secondaryOutputToken,\n address(params.contracts.multichainVault), // receiver\n result.secondaryOutputAmount,\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n result.secondaryOutputToken,\n order.receiver(),\n order.srcChainId()\n );\n }\n\n return getOutputEventData(\n result.outputToken,\n result.outputAmount,\n result.secondaryOutputToken,\n result.secondaryOutputAmount,\n result.orderSizeDeltaUsd,\n result.orderInitialCollateralDeltaAmount\n );\n }\n\n try params.contracts.swapHandler.swap(\n ISwapUtils.SwapParams(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.oracle,\n Bank(payable(order.market())),\n params.key,\n result.outputToken,\n result.outputAmount,\n params.swapPathMarkets,\n 0,\n order.srcChainId() == 0 ? order.receiver(): address(params.contracts.multichainVault),\n order.uiFeeReceiver(),\n order.srcChainId() == 0 ? order.shouldUnwrapNativeToken() : false,\n ISwapPricingUtils.SwapPricingType.Swap\n )\n ) returns (address tokenOut, uint256 swapOutputAmount) {\n _validateOutputAmount(\n params.contracts.oracle,\n tokenOut,\n swapOutputAmount,\n order.minOutputAmount()\n );\n\n if (order.srcChainId() != 0) {\n MultichainUtils.recordTransferIn(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n tokenOut,\n order.receiver(),\n order.srcChainId()\n );\n }\n\n return getOutputEventData(\n tokenOut,\n swapOutputAmount,\n address(0),\n 0,\n result.orderSizeDeltaUsd,\n result.orderInitialCollateralDeltaAmount\n );\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n\n _handleSwapError(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n params.contracts.oracle,\n order,\n result,\n reason,\n reasonBytes\n );\n\n return getOutputEventData(\n result.outputToken,\n result.outputAmount,\n address(0),\n 0,\n result.orderSizeDeltaUsd,\n result.orderInitialCollateralDeltaAmount\n );\n }\n }\n\n function validateOracleTimestamp(\n DataStore dataStore,\n Order.OrderType orderType,\n uint256 orderUpdatedAtTime,\n uint256 orderValidFromTime,\n uint256 positionIncreasedAtTime,\n uint256 positionDecreasedAtTime,\n uint256 minOracleTimestamp,\n uint256 maxOracleTimestamp\n ) internal view {\n if (orderType == Order.OrderType.MarketDecrease) {\n if (minOracleTimestamp < orderUpdatedAtTime) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, orderUpdatedAtTime);\n }\n\n uint256 requestExpirationTime = dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);\n\n if (maxOracleTimestamp > orderUpdatedAtTime + requestExpirationTime) {\n revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(\n maxOracleTimestamp,\n orderUpdatedAtTime,\n requestExpirationTime\n );\n }\n return;\n }\n\n if (\n !Order.isMarketOrder(orderType) &&\n minOracleTimestamp < orderValidFromTime\n ) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, orderValidFromTime);\n }\n\n // a user could attempt to frontrun prices by creating a limit decrease\n // order without a position\n // when price moves in the user's favour, the user would create a\n // position then\n // e.g. price is $5000, a user creates a stop-loss order to\n // close a long position when price is below $5000\n // if price decreases to $4995, the user opens a long position at\n // price $4995\n // since slightly older prices may be used to execute a position\n // the user's stop-loss order could be executed at price $5000\n // for this reason, both the orderUpdatedAtTime and the\n // positionIncreasedAtTime need to be used as a reference\n //\n // if there are multiple decrease orders, an execution of one decrease\n // order would update the position, so the reference check here is only\n // with positionIncreasedAtTime instead of a positionUpdatedAtTime value\n if (\n orderType == Order.OrderType.LimitDecrease ||\n orderType == Order.OrderType.StopLossDecrease\n ) {\n uint256 latestUpdatedAtTime = orderUpdatedAtTime > positionIncreasedAtTime ? orderUpdatedAtTime : positionIncreasedAtTime;\n if (minOracleTimestamp < latestUpdatedAtTime) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, latestUpdatedAtTime);\n }\n return;\n }\n\n if (orderType == Order.OrderType.Liquidation) {\n uint256 latestUpdatedAtTime = positionIncreasedAtTime > positionDecreasedAtTime ? positionIncreasedAtTime : positionDecreasedAtTime;\n if (minOracleTimestamp < latestUpdatedAtTime) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, latestUpdatedAtTime);\n }\n return;\n }\n\n revert Errors.UnsupportedOrderType(uint256(orderType));\n }\n\n // note that minOutputAmount is treated as a USD value for this validation\n function _validateOutputAmount(\n IOracle oracle,\n address outputToken,\n uint256 outputAmount,\n uint256 minOutputAmount\n ) internal view {\n uint256 outputTokenPrice = oracle.getPrimaryPrice(outputToken).min;\n uint256 outputUsd = outputAmount * outputTokenPrice;\n\n if (outputUsd < minOutputAmount) {\n revert Errors.InsufficientOutputAmount(outputUsd, minOutputAmount);\n }\n }\n\n // note that minOutputAmount is treated as a USD value for this validation\n function _validateOutputAmount(\n IOracle oracle,\n address outputToken,\n uint256 outputAmount,\n address secondaryOutputToken,\n uint256 secondaryOutputAmount,\n uint256 minOutputAmount\n ) internal view {\n uint256 outputTokenPrice = oracle.getPrimaryPrice(outputToken).min;\n uint256 outputUsd = outputAmount * outputTokenPrice;\n\n uint256 secondaryOutputTokenPrice = oracle.getPrimaryPrice(secondaryOutputToken).min;\n uint256 secondaryOutputUsd = secondaryOutputAmount * secondaryOutputTokenPrice;\n\n uint256 totalOutputUsd = outputUsd + secondaryOutputUsd;\n\n if (totalOutputUsd < minOutputAmount) {\n revert Errors.InsufficientOutputAmount(totalOutputUsd, minOutputAmount);\n }\n }\n\n function _handleSwapError(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n IOracle oracle,\n Order.Props memory order,\n DecreasePositionUtils.DecreasePositionResult memory result,\n string memory reason,\n bytes memory reasonBytes\n ) internal {\n emit SwapUtils.SwapReverted(reason, reasonBytes);\n\n _validateOutputAmount(\n oracle,\n result.outputToken,\n result.outputAmount,\n order.minOutputAmount()\n );\n\n if (order.srcChainId() == 0) {\n MarketToken(payable(order.market())).transferOut(\n result.outputToken,\n order.receiver(),\n result.outputAmount,\n order.shouldUnwrapNativeToken()\n );\n } else {\n MarketToken(payable(order.market())).transferOut(\n result.outputToken,\n address(multichainVault),\n result.outputAmount,\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n result.outputToken,\n order.receiver(),\n 0 // srcChainId is the current block.chainId\n );\n }\n }\n\n function getOutputEventData(\n address outputToken,\n uint256 outputAmount,\n address secondaryOutputToken,\n uint256 secondaryOutputAmount,\n uint256 orderSizeDeltaUsd,\n uint256 orderInitialCollateralDeltaAmount\n ) internal pure returns (EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"outputToken\", outputToken);\n eventData.addressItems.setItem(1, \"secondaryOutputToken\", secondaryOutputToken);\n\n eventData.uintItems.initItems(4);\n eventData.uintItems.setItem(0, \"outputAmount\", outputAmount);\n eventData.uintItems.setItem(1, \"secondaryOutputAmount\", secondaryOutputAmount);\n eventData.uintItems.setItem(2, \"orderSizeDeltaUsd\", orderSizeDeltaUsd);\n eventData.uintItems.setItem(3, \"orderInitialCollateralDeltaAmount\", orderInitialCollateralDeltaAmount);\n\n return eventData;\n }\n}\n" + }, + "contracts/order/ExecuteOrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\n\nimport \"./Order.sol\";\nimport \"./OrderVault.sol\";\nimport \"./OrderStoreUtils.sol\";\nimport \"./OrderEventUtils.sol\";\nimport \"./OrderUtils.sol\";\n\nimport \"../event/EventEmitter.sol\";\n\nimport \"../exchange/IOrderExecutor.sol\";\nimport \"../position/PositionUtils.sol\";\nimport \"../position/PositionStoreUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\n\nimport \"../utils/Array.sol\";\n\nlibrary ExecuteOrderUtils {\n using Order for Order.Props;\n using Position for Position.Props;\n using Price for Price.Props;\n using Array for uint256[];\n\n // @dev executes an order\n // @param params BaseOrderUtils.ExecuteOrderParams\n function executeOrder(IOrderExecutor orderExecutor, BaseOrderUtils.ExecuteOrderParams memory params) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n OrderStoreUtils.remove(params.contracts.dataStore, params.key, params.order.account());\n\n BaseOrderUtils.validateNonEmptyOrder(params.order);\n\n BaseOrderUtils.validateOrderTriggerPrice(\n params.contracts.oracle,\n params.market.indexToken,\n params.order.orderType(),\n params.order.triggerPrice(),\n params.order.isLong()\n );\n\n BaseOrderUtils.validateOrderValidFromTime(\n params.order.orderType(),\n params.order.validFromTime()\n );\n\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(\n params.contracts.oracle,\n params.market\n );\n\n MarketUtils.distributePositionImpactPool(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken\n );\n\n PositionUtils.updateFundingAndBorrowingState(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n prices\n );\n\n EventUtils.EventLogData memory eventData = orderExecutor.processOrder(params);\n\n\n // validate that internal state changes are correct before calling\n // external callbacks\n // if the native token was transferred to the receiver in a swap\n // it may be possible to invoke external contracts before the validations\n // are called\n if (params.market.marketToken != address(0)) {\n MarketUtils.validateMarketTokenBalance(params.contracts.dataStore, params.market);\n }\n MarketUtils.validateMarketTokenBalance(params.contracts.dataStore, params.swapPathMarkets);\n\n OrderUtils.updateAutoCancelList(params.contracts.dataStore, params.key, params.order, false);\n\n OrderEventUtils.emitOrderExecuted(\n params.contracts.eventEmitter,\n params.key,\n params.order.account(),\n params.secondaryOrderType\n );\n\n CallbackUtils.afterOrderExecution(params.key, params.order, eventData);\n\n // the order.executionFee for liquidation / adl orders is zero\n // gas costs for liquidations / adl is subsidised by the treasury\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n params.contracts.orderVault\n ),\n params.key,\n params.order.callbackContract(),\n params.order.executionFee(),\n params.startingGas,\n GasUtils.estimateOrderOraclePriceCount(params.order.swapPath().length),\n params.keeper,\n params.order.receiver(),\n params.order.srcChainId()\n );\n\n // clearAutoCancelOrders should be called after the main execution fee\n // is called\n // this is because clearAutoCancelOrders loops through each order for\n // the associated position and calls cancelOrder, which pays the keeper\n // based on the gas usage for each cancel order\n if (Order.isDecreaseOrder(params.order.orderType())) {\n bytes32 positionKey = BaseOrderUtils.getPositionKey(params.order);\n uint256 sizeInUsd = params.contracts.dataStore.getUint(\n keccak256(abi.encode(positionKey, PositionStoreUtils.SIZE_IN_USD))\n );\n if (sizeInUsd == 0) {\n OrderUtils.clearAutoCancelOrders(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n params.contracts.orderVault,\n positionKey,\n params.keeper\n );\n }\n }\n }\n}\n" + }, + "contracts/order/IBaseOrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./Order.sol\";\n\ninterface IBaseOrderUtils {\n // @dev CreateOrderParams struct used in createOrder to avoid stack\n // too deep errors\n //\n // @param addresses address values\n // @param numbers number values\n // @param orderType for order.orderType\n // @param decreasePositionSwapType for order.decreasePositionSwapType\n // @param isLong for order.isLong\n // @param shouldUnwrapNativeToken for order.shouldUnwrapNativeToken\n // @param dataList a list of bytes32 values that can be used for additional data\n // @note all params except should be part of the corresponding struct hash in all relay contracts\n struct CreateOrderParams {\n CreateOrderParamsAddresses addresses;\n CreateOrderParamsNumbers numbers;\n Order.OrderType orderType;\n Order.DecreasePositionSwapType decreasePositionSwapType;\n bool isLong;\n bool shouldUnwrapNativeToken;\n bool autoCancel;\n bytes32 referralCode;\n bytes32[] dataList;\n }\n\n // @note all params except should be part of the corresponding struct hash in all relay contracts\n struct CreateOrderParamsAddresses {\n address receiver;\n address cancellationReceiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address initialCollateralToken;\n address[] swapPath;\n }\n\n // @param sizeDeltaUsd for order.sizeDeltaUsd\n // @param triggerPrice for order.triggerPrice\n // @param acceptablePrice for order.acceptablePrice\n // @param executionFee for order.executionFee\n // @param callbackGasLimit for order.callbackGasLimit\n // @param minOutputAmount for order.minOutputAmount\n // @param validFromTime for order.validFromTime\n // @note all params except should be part of the corresponding struct hash in all relay contracts\n struct CreateOrderParamsNumbers {\n uint256 sizeDeltaUsd;\n uint256 initialCollateralDeltaAmount;\n uint256 triggerPrice;\n uint256 acceptablePrice;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 minOutputAmount;\n uint256 validFromTime;\n }\n}\n" + }, + "contracts/order/IncreaseOrderExecutor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../exchange/IOrderExecutor.sol\";\nimport \"./IncreaseOrderUtils.sol\";\n\ncontract IncreaseOrderExecutor is ReentrancyGuard, RoleModule {\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) external nonReentrant onlyController returns (EventUtils.EventLogData memory) {\n return IncreaseOrderUtils.processOrder(params);\n }\n}\n" + }, + "contracts/order/IncreaseOrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseOrderUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\nimport \"../position/IncreasePositionUtils.sol\";\n\n// @title IncreaseOrderUtils\n// @dev Library for functions to help with processing an increase order\nlibrary IncreaseOrderUtils {\n using Position for Position.Props;\n using Order for Order.Props;\n using Array for uint256[];\n\n // @dev process an increase order\n // @param params BaseOrderUtils.ExecuteOrderParams\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {\n MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market);\n\n (address collateralToken, uint256 collateralIncrementAmount) = params.contracts.swapHandler.swap(ISwapUtils.SwapParams(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.oracle,\n params.contracts.orderVault,\n params.key,\n params.order.initialCollateralToken(),\n params.order.initialCollateralDeltaAmount(),\n params.swapPathMarkets,\n params.order.minOutputAmount(),\n params.order.market(),\n params.order.uiFeeReceiver(),\n false,\n ISwapPricingUtils.SwapPricingType.Swap\n ));\n\n MarketUtils.validateMarketCollateralToken(params.market, collateralToken);\n\n bytes32 positionKey = Position.getPositionKey(params.order.account(), params.order.market(), collateralToken, params.order.isLong());\n Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey);\n\n // initialize position\n if (position.account() == address(0)) {\n position.setAccount(params.order.account());\n if (position.market() != address(0) || position.collateralToken() != address(0)) {\n revert Errors.UnexpectedPositionState();\n }\n\n position.setMarket(params.order.market());\n position.setCollateralToken(collateralToken);\n position.setIsLong(params.order.isLong());\n }\n\n if (params.minOracleTimestamp < params.order.updatedAtTime()) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(\n params.minOracleTimestamp,\n params.order.updatedAtTime()\n );\n }\n\n if (\n !Order.isMarketOrder(params.order.orderType()) &&\n params.minOracleTimestamp < params.order.validFromTime()\n ) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(\n params.minOracleTimestamp,\n params.order.validFromTime()\n );\n }\n\n uint256 requestExpirationTime = params.contracts.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);\n\n if (\n params.order.orderType() == Order.OrderType.MarketIncrease &&\n params.maxOracleTimestamp > params.order.updatedAtTime() + requestExpirationTime\n ) {\n revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(\n params.maxOracleTimestamp,\n params.order.updatedAtTime(),\n requestExpirationTime\n );\n }\n\n IncreasePositionUtils.increasePosition(\n PositionUtils.UpdatePositionParams(\n params.contracts,\n params.market,\n params.order,\n params.key,\n position,\n positionKey,\n params.secondaryOrderType\n ),\n collateralIncrementAmount\n );\n\n EventUtils.EventLogData memory eventData;\n return eventData;\n }\n}\n" + }, + "contracts/order/Order.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../chain/Chain.sol\";\n\n// @title Order\n// @dev Struct for orders\nlibrary Order {\n using Order for Props;\n\n enum OrderType {\n // @dev MarketSwap: swap token A to token B at the current market price\n // the order will be cancelled if the minOutputAmount cannot be fulfilled\n MarketSwap,\n // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled\n LimitSwap,\n // @dev MarketIncrease: increase position at the current market price\n // the order will be cancelled if the position cannot be increased at the acceptablePrice\n MarketIncrease,\n // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\n LimitIncrease,\n // @dev MarketDecrease: decrease position at the current market price\n // the order will be cancelled if the position cannot be decreased at the acceptablePrice\n MarketDecrease,\n // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\n LimitDecrease,\n // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled\n StopLossDecrease,\n // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met\n Liquidation,\n // @dev StopIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled\n StopIncrease\n }\n\n // to help further differentiate orders\n enum SecondaryOrderType {\n None,\n Adl\n }\n\n enum DecreasePositionSwapType {\n NoSwap,\n SwapPnlTokenToCollateralToken,\n SwapCollateralTokenToPnlToken\n }\n\n // @dev there is a limit on the number of fields a struct can have when being passed\n // or returned as a memory variable which can cause \"Stack too deep\" errors\n // use sub-structs to avoid this issue\n // @param addresses address values\n // @param numbers number values\n // @param flags boolean values\n // @param _dataList a list of bytes32 values that can be used for additional data\n struct Props {\n Addresses addresses;\n Numbers numbers;\n Flags flags;\n bytes32[] _dataList;\n }\n\n // @param account the account of the order\n // @param receiver the receiver for any token transfers\n // this field is meant to allow the output of an order to be\n // received by an address that is different from the creator of the\n // order whether this is for swaps or whether the account is the owner\n // of a position\n // for funding fees and claimable collateral, the funds are still\n // credited to the owner of the position indicated by order.account\n // @param callbackContract the contract to call for callbacks\n // @param uiFeeReceiver the ui fee receiver\n // @param market the trading market\n // @param initialCollateralToken for increase orders, initialCollateralToken\n // is the token sent in by the user, the token will be swapped through the\n // specified swapPath, before being deposited into the position as collateral\n // for decrease orders, initialCollateralToken is the collateral token of the position\n // withdrawn collateral from the decrease of the position will be swapped\n // through the specified swapPath\n // for swaps, initialCollateralToken is the initial token sent for the swap\n // @param swapPath an array of market addresses to swap through\n struct Addresses {\n address account;\n address receiver;\n address cancellationReceiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address initialCollateralToken;\n address[] swapPath;\n }\n\n // @param sizeDeltaUsd the requested change in position size\n // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount\n // is the amount of the initialCollateralToken sent in by the user\n // for decrease orders, initialCollateralDeltaAmount is the amount of the position's\n // collateralToken to withdraw\n // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent\n // in for the swap\n // @param orderType the order type\n // @param triggerPrice the trigger price for non-market orders\n // @param acceptablePrice the acceptable execution price for increase / decrease orders\n // @param executionFee the execution fee for keepers\n // @param callbackGasLimit the gas limit for the callbackContract\n // @param minOutputAmount the minimum output amount for decrease orders and swaps\n // note that for decrease orders, multiple tokens could be received, for this reason, the\n // minOutputAmount value is treated as a USD value for validation in decrease orders\n // @param srcChainId the source chain id\n struct Numbers {\n OrderType orderType;\n DecreasePositionSwapType decreasePositionSwapType;\n uint256 sizeDeltaUsd;\n uint256 initialCollateralDeltaAmount;\n uint256 triggerPrice;\n uint256 acceptablePrice;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 minOutputAmount;\n uint256 updatedAtTime;\n uint256 validFromTime;\n uint256 srcChainId;\n }\n\n // @param isLong whether the order is for a long or short\n // @param shouldUnwrapNativeToken whether to unwrap native tokens before\n // transferring to the user\n // @param isFrozen whether the order is frozen\n struct Flags {\n bool isLong;\n bool shouldUnwrapNativeToken;\n bool isFrozen;\n bool autoCancel;\n }\n\n // @dev the order account\n // @param props Props\n // @return the order account\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n // @dev set the order account\n // @param props Props\n // @param value the value to set to\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n // @dev the order receiver\n // @param props Props\n // @return the order receiver\n function receiver(Props memory props) internal pure returns (address) {\n return props.addresses.receiver;\n }\n\n // @dev set the order receiver\n // @param props Props\n // @param value the value to set to\n function setReceiver(Props memory props, address value) internal pure {\n props.addresses.receiver = value;\n }\n\n function cancellationReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.cancellationReceiver;\n }\n\n function setCancellationReceiver(Props memory props, address value) internal pure {\n props.addresses.cancellationReceiver = value;\n }\n\n // @dev the order callbackContract\n // @param props Props\n // @return the order callbackContract\n function callbackContract(Props memory props) internal pure returns (address) {\n return props.addresses.callbackContract;\n }\n\n // @dev set the order callbackContract\n // @param props Props\n // @param value the value to set to\n function setCallbackContract(Props memory props, address value) internal pure {\n props.addresses.callbackContract = value;\n }\n\n // @dev the order market\n // @param props Props\n // @return the order market\n function market(Props memory props) internal pure returns (address) {\n return props.addresses.market;\n }\n\n // @dev set the order market\n // @param props Props\n // @param value the value to set to\n function setMarket(Props memory props, address value) internal pure {\n props.addresses.market = value;\n }\n\n // @dev the order initialCollateralToken\n // @param props Props\n // @return the order initialCollateralToken\n function initialCollateralToken(Props memory props) internal pure returns (address) {\n return props.addresses.initialCollateralToken;\n }\n\n // @dev set the order initialCollateralToken\n // @param props Props\n // @param value the value to set to\n function setInitialCollateralToken(Props memory props, address value) internal pure {\n props.addresses.initialCollateralToken = value;\n }\n\n // @dev the order uiFeeReceiver\n // @param props Props\n // @return the order uiFeeReceiver\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.uiFeeReceiver;\n }\n\n // @dev set the order uiFeeReceiver\n // @param props Props\n // @param value the value to set to\n function setUiFeeReceiver(Props memory props, address value) internal pure {\n props.addresses.uiFeeReceiver = value;\n }\n\n // @dev the order swapPath\n // @param props Props\n // @return the order swapPath\n function swapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.swapPath;\n }\n\n // @dev set the order swapPath\n // @param props Props\n // @param value the value to set to\n function setSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.swapPath = value;\n }\n\n // @dev the order type\n // @param props Props\n // @return the order type\n function orderType(Props memory props) internal pure returns (OrderType) {\n return props.numbers.orderType;\n }\n\n // @dev set the order type\n // @param props Props\n // @param value the value to set to\n function setOrderType(Props memory props, OrderType value) internal pure {\n props.numbers.orderType = value;\n }\n\n function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {\n return props.numbers.decreasePositionSwapType;\n }\n\n function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {\n props.numbers.decreasePositionSwapType = value;\n }\n\n // @dev the order sizeDeltaUsd\n // @param props Props\n // @return the order sizeDeltaUsd\n function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {\n return props.numbers.sizeDeltaUsd;\n }\n\n // @dev set the order sizeDeltaUsd\n // @param props Props\n // @param value the value to set to\n function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {\n props.numbers.sizeDeltaUsd = value;\n }\n\n // @dev the order initialCollateralDeltaAmount\n // @param props Props\n // @return the order initialCollateralDeltaAmount\n function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.initialCollateralDeltaAmount;\n }\n\n // @dev set the order initialCollateralDeltaAmount\n // @param props Props\n // @param value the value to set to\n function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {\n props.numbers.initialCollateralDeltaAmount = value;\n }\n\n // @dev the order triggerPrice\n // @param props Props\n // @return the order triggerPrice\n function triggerPrice(Props memory props) internal pure returns (uint256) {\n return props.numbers.triggerPrice;\n }\n\n // @dev set the order triggerPrice\n // @param props Props\n // @param value the value to set to\n function setTriggerPrice(Props memory props, uint256 value) internal pure {\n props.numbers.triggerPrice = value;\n }\n\n // @dev the order acceptablePrice\n // @param props Props\n // @return the order acceptablePrice\n function acceptablePrice(Props memory props) internal pure returns (uint256) {\n return props.numbers.acceptablePrice;\n }\n\n // @dev set the order acceptablePrice\n // @param props Props\n // @param value the value to set to\n function setAcceptablePrice(Props memory props, uint256 value) internal pure {\n props.numbers.acceptablePrice = value;\n }\n\n // @dev set the order executionFee\n // @param props Props\n // @param value the value to set to\n function setExecutionFee(Props memory props, uint256 value) internal pure {\n props.numbers.executionFee = value;\n }\n\n // @dev the order executionFee\n // @param props Props\n // @return the order executionFee\n function executionFee(Props memory props) internal pure returns (uint256) {\n return props.numbers.executionFee;\n }\n\n // @dev the order callbackGasLimit\n // @param props Props\n // @return the order callbackGasLimit\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\n return props.numbers.callbackGasLimit;\n }\n\n // @dev set the order callbackGasLimit\n // @param props Props\n // @param value the value to set to\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\n props.numbers.callbackGasLimit = value;\n }\n\n // @dev the order minOutputAmount\n // @param props Props\n // @return the order minOutputAmount\n function minOutputAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.minOutputAmount;\n }\n\n // @dev set the order minOutputAmount\n // @param props Props\n // @param value the value to set to\n function setMinOutputAmount(Props memory props, uint256 value) internal pure {\n props.numbers.minOutputAmount = value;\n }\n\n // @dev the order updatedAtTime\n // @param props Props\n // @return the order updatedAtTime\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n // @dev set the order updatedAtTime\n // @param props Props\n // @param value the value to set to\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n\n function validFromTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.validFromTime;\n }\n function setValidFromTime(Props memory props, uint256 value) internal pure {\n props.numbers.validFromTime = value;\n }\n\n function srcChainId(Props memory props) internal pure returns (uint256) {\n return props.numbers.srcChainId;\n }\n function setSrcChainId(Props memory props, uint256 value) internal pure {\n props.numbers.srcChainId = value;\n }\n\n // @dev whether the order is for a long or short\n // @param props Props\n // @return whether the order is for a long or short\n function isLong(Props memory props) internal pure returns (bool) {\n return props.flags.isLong;\n }\n\n // @dev set whether the order is for a long or short\n // @param props Props\n // @param value the value to set to\n function setIsLong(Props memory props, bool value) internal pure {\n props.flags.isLong = value;\n }\n\n // @dev whether to unwrap the native token before transfers to the user\n // @param props Props\n // @return whether to unwrap the native token before transfers to the user\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\n return props.flags.shouldUnwrapNativeToken;\n }\n\n // @dev set whether the native token should be unwrapped before being\n // transferred to the receiver\n // @param props Props\n // @param value the value to set to\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\n props.flags.shouldUnwrapNativeToken = value;\n }\n\n // @dev whether the order is frozen\n // @param props Props\n // @return whether the order is frozen\n function isFrozen(Props memory props) internal pure returns (bool) {\n return props.flags.isFrozen;\n }\n\n // @dev set whether the order is frozen\n // transferred to the receiver\n // @param props Props\n // @param value the value to set to\n function setIsFrozen(Props memory props, bool value) internal pure {\n props.flags.isFrozen = value;\n }\n\n function autoCancel(Props memory props) internal pure returns (bool) {\n return props.flags.autoCancel;\n }\n\n function setAutoCancel(Props memory props, bool value) internal pure {\n props.flags.autoCancel = value;\n }\n\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\n return props._dataList;\n }\n\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\n props._dataList = value;\n }\n\n // @param props Props\n function touch(Props memory props) internal view {\n props.setUpdatedAtTime(Chain.currentTimestamp());\n }\n\n function isSupportedOrder(OrderType _orderType) internal pure returns (bool) {\n return _orderType == OrderType.MarketSwap ||\n _orderType == OrderType.LimitSwap ||\n _orderType == OrderType.MarketIncrease ||\n _orderType == OrderType.MarketDecrease ||\n _orderType == OrderType.LimitIncrease ||\n _orderType == OrderType.LimitDecrease ||\n _orderType == OrderType.StopIncrease ||\n _orderType == OrderType.StopLossDecrease ||\n _orderType == OrderType.Liquidation;\n }\n\n // @dev check if an orderType is a market order\n // @param orderType the order type\n // @return whether an orderType is a market order\n function isMarketOrder(OrderType _orderType) internal pure returns (bool) {\n // a liquidation order is not considered as a market order\n return _orderType == OrderType.MarketSwap ||\n _orderType == OrderType.MarketIncrease ||\n _orderType == OrderType.MarketDecrease;\n }\n\n // @dev check if an orderType is a swap order\n // @param orderType the order type\n // @return whether an orderType is a swap order\n function isSwapOrder(OrderType _orderType) internal pure returns (bool) {\n return _orderType == OrderType.MarketSwap ||\n _orderType == OrderType.LimitSwap;\n }\n\n // @dev check if an orderType is a position order\n // @param orderType the order type\n // @return whether an orderType is a position order\n function isPositionOrder(OrderType _orderType) internal pure returns (bool) {\n return isIncreaseOrder(_orderType) || isDecreaseOrder(_orderType);\n }\n\n // @dev check if an orderType is an increase order\n // @param orderType the order type\n // @return whether an orderType is an increase order\n function isIncreaseOrder(OrderType _orderType) internal pure returns (bool) {\n return _orderType == OrderType.MarketIncrease ||\n _orderType == OrderType.LimitIncrease ||\n _orderType == OrderType.StopIncrease;\n }\n\n // @dev check if an orderType is a decrease order\n // @param orderType the order type\n // @return whether an orderType is a decrease order\n function isDecreaseOrder(OrderType _orderType) internal pure returns (bool) {\n return _orderType == OrderType.MarketDecrease ||\n _orderType == OrderType.LimitDecrease ||\n _orderType == OrderType.StopLossDecrease ||\n _orderType == OrderType.Liquidation;\n }\n\n // @dev check if an orderType is a liquidation order\n // @param orderType the order type\n // @return whether an orderType is a liquidation order\n function isLiquidationOrder(OrderType _orderType) internal pure returns (bool) {\n return _orderType == OrderType.Liquidation;\n }\n}\n" + }, + "contracts/order/OrderEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/Cast.sol\";\n\nimport \"./Order.sol\";\n\nlibrary OrderEventUtils {\n using Order for Order.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitOrderCreated(\n EventEmitter eventEmitter,\n bytes32 key,\n Order.Props memory order\n ) external {\n EventUtils.EventLogData memory eventData = createEventData(order);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog2(\n \"OrderCreated\",\n key,\n Cast.toBytes32(order.account()),\n eventData\n );\n }\n\n function emitOrderExecuted(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n Order.SecondaryOrderType secondaryOrderType\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"secondaryOrderType\", uint256(secondaryOrderType));\n\n eventEmitter.emitEventLog2(\n \"OrderExecuted\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitOrderUpdated(\n EventEmitter eventEmitter,\n bytes32 key,\n Order.Props memory order\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", order.account());\n\n eventData.uintItems.initItems(6);\n eventData.uintItems.setItem(0, \"sizeDeltaUsd\", order.sizeDeltaUsd());\n eventData.uintItems.setItem(1, \"acceptablePrice\", order.acceptablePrice());\n eventData.uintItems.setItem(2, \"triggerPrice\", order.triggerPrice());\n eventData.uintItems.setItem(3, \"minOutputAmount\", order.minOutputAmount());\n eventData.uintItems.setItem(4, \"updatedAtTime\", order.updatedAtTime());\n eventData.uintItems.setItem(5, \"validFromTime\", order.validFromTime());\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"autoCancel\", order.autoCancel());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", order.dataList());\n\n eventEmitter.emitEventLog2(\n \"OrderUpdated\",\n key,\n Cast.toBytes32(order.account()),\n eventData\n );\n }\n\n function emitOrderSizeDeltaAutoUpdated(\n EventEmitter eventEmitter,\n bytes32 key,\n uint256 sizeDeltaUsd,\n uint256 nextSizeDeltaUsd\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"sizeDeltaUsd\", sizeDeltaUsd);\n eventData.uintItems.setItem(1, \"nextSizeDeltaUsd\", nextSizeDeltaUsd);\n\n eventEmitter.emitEventLog1(\n \"OrderSizeDeltaAutoUpdated\",\n key,\n eventData\n );\n }\n\n function emitOrderCollateralDeltaAmountAutoUpdated(\n EventEmitter eventEmitter,\n bytes32 key,\n uint256 collateralDeltaAmount,\n uint256 nextCollateralDeltaAmount\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"collateralDeltaAmount\", collateralDeltaAmount);\n eventData.uintItems.setItem(1, \"nextCollateralDeltaAmount\", nextCollateralDeltaAmount);\n\n eventEmitter.emitEventLog1(\n \"OrderCollateralDeltaAmountAutoUpdated\",\n key,\n eventData\n );\n }\n\n function emitOrderCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\n \"OrderCancelled\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitOrderFrozen(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\n \"OrderFrozen\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function createEventData(Order.Props memory order) public pure returns (EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(7);\n eventData.addressItems.setItem(0, \"account\", order.account());\n eventData.addressItems.setItem(1, \"receiver\", order.receiver());\n eventData.addressItems.setItem(2, \"callbackContract\", order.callbackContract());\n eventData.addressItems.setItem(3, \"uiFeeReceiver\", order.uiFeeReceiver());\n eventData.addressItems.setItem(4, \"market\", order.market());\n eventData.addressItems.setItem(5, \"initialCollateralToken\", order.initialCollateralToken());\n eventData.addressItems.setItem(6, \"cancellationReceiver\", order.cancellationReceiver());\n\n eventData.addressItems.initArrayItems(1);\n eventData.addressItems.setItem(0, \"swapPath\", order.swapPath());\n\n eventData.uintItems.initItems(12);\n eventData.uintItems.setItem(0, \"orderType\", uint256(order.orderType()));\n eventData.uintItems.setItem(1, \"decreasePositionSwapType\", uint256(order.decreasePositionSwapType()));\n eventData.uintItems.setItem(2, \"sizeDeltaUsd\", order.sizeDeltaUsd());\n eventData.uintItems.setItem(3, \"initialCollateralDeltaAmount\", order.initialCollateralDeltaAmount());\n eventData.uintItems.setItem(4, \"triggerPrice\", order.triggerPrice());\n eventData.uintItems.setItem(5, \"acceptablePrice\", order.acceptablePrice());\n eventData.uintItems.setItem(6, \"executionFee\", order.executionFee());\n eventData.uintItems.setItem(7, \"callbackGasLimit\", order.callbackGasLimit());\n eventData.uintItems.setItem(8, \"minOutputAmount\", order.minOutputAmount());\n eventData.uintItems.setItem(9, \"updatedAtTime\", order.updatedAtTime());\n eventData.uintItems.setItem(10, \"validFromTime\", order.validFromTime());\n eventData.uintItems.setItem(11, \"srcChainId\", order.srcChainId());\n\n eventData.boolItems.initItems(3);\n eventData.boolItems.setItem(0, \"isLong\", order.isLong());\n eventData.boolItems.setItem(1, \"shouldUnwrapNativeToken\", order.shouldUnwrapNativeToken());\n eventData.boolItems.setItem(2, \"autoCancel\", order.autoCancel());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", order.dataList());\n return eventData;\n }\n\n function emitPositionCollateralUsedForExecutionFee(\n EventEmitter eventEmitter,\n bytes32 orderKey,\n address feeToken,\n uint256 positionCollateralAmountUsed\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", orderKey);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"feeToken\", feeToken);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"positionCollateralAmountUsed\", positionCollateralAmountUsed);\n\n eventEmitter.emitEventLog1(\n \"PositionCollateralUsedForExecutionFee\",\n orderKey,\n eventData\n );\n }\n}\n" + }, + "contracts/order/OrderStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Order.sol\";\n\n/**\n * @title OrderStoreUtils\n * @dev Library for order storage functions\n */\nlibrary OrderStoreUtils {\n using Order for Order.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant RECEIVER = keccak256(abi.encode(\"RECEIVER\"));\n bytes32 public constant CANCELLATION_RECEIVER = keccak256(abi.encode(\"CANCELLATION_RECEIVER\"));\n bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode(\"CALLBACK_CONTRACT\"));\n bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode(\"UI_FEE_RECEIVER\"));\n bytes32 public constant MARKET = keccak256(abi.encode(\"MARKET\"));\n bytes32 public constant INITIAL_COLLATERAL_TOKEN = keccak256(abi.encode(\"INITIAL_COLLATERAL_TOKEN\"));\n bytes32 public constant SWAP_PATH = keccak256(abi.encode(\"SWAP_PATH\"));\n\n bytes32 public constant ORDER_TYPE = keccak256(abi.encode(\"ORDER_TYPE\"));\n bytes32 public constant DECREASE_POSITION_SWAP_TYPE = keccak256(abi.encode(\"DECREASE_POSITION_SWAP_TYPE\"));\n bytes32 public constant SIZE_DELTA_USD = keccak256(abi.encode(\"SIZE_DELTA_USD\"));\n bytes32 public constant INITIAL_COLLATERAL_DELTA_AMOUNT = keccak256(abi.encode(\"INITIAL_COLLATERAL_DELTA_AMOUNT\"));\n bytes32 public constant TRIGGER_PRICE = keccak256(abi.encode(\"TRIGGER_PRICE\"));\n bytes32 public constant ACCEPTABLE_PRICE = keccak256(abi.encode(\"ACCEPTABLE_PRICE\"));\n bytes32 public constant EXECUTION_FEE = keccak256(abi.encode(\"EXECUTION_FEE\"));\n bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"CALLBACK_GAS_LIMIT\"));\n bytes32 public constant MIN_OUTPUT_AMOUNT = keccak256(abi.encode(\"MIN_OUTPUT_AMOUNT\"));\n bytes32 public constant VALID_FROM_TIME = keccak256(abi.encode(\"VALID_FROM_TIME\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n bytes32 public constant SRC_CHAIN_ID = keccak256(abi.encode(\"SRC_CHAIN_ID\"));\n\n bytes32 public constant IS_LONG = keccak256(abi.encode(\"IS_LONG\"));\n bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode(\"SHOULD_UNWRAP_NATIVE_TOKEN\"));\n bytes32 public constant IS_FROZEN = keccak256(abi.encode(\"IS_FROZEN\"));\n bytes32 public constant AUTO_CANCEL = keccak256(abi.encode(\"AUTO_CANCEL\"));\n\n bytes32 public constant DATA_LIST = keccak256(abi.encode(\"DATA_LIST\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (Order.Props memory) {\n Order.Props memory order;\n if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) {\n return order;\n }\n\n order.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n order.setReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, RECEIVER))\n ));\n\n order.setCancellationReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, CANCELLATION_RECEIVER))\n ));\n\n order.setCallbackContract(dataStore.getAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n ));\n\n order.setUiFeeReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n ));\n\n order.setMarket(dataStore.getAddress(\n keccak256(abi.encode(key, MARKET))\n ));\n\n order.setInitialCollateralToken(dataStore.getAddress(\n keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN))\n ));\n\n order.setSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, SWAP_PATH))\n ));\n\n order.setOrderType(Order.OrderType(dataStore.getUint(\n keccak256(abi.encode(key, ORDER_TYPE))\n )));\n\n order.setDecreasePositionSwapType(Order.DecreasePositionSwapType(dataStore.getUint(\n keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE))\n )));\n\n order.setSizeDeltaUsd(dataStore.getUint(\n keccak256(abi.encode(key, SIZE_DELTA_USD))\n ));\n\n order.setInitialCollateralDeltaAmount(dataStore.getUint(\n keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT))\n ));\n\n order.setTriggerPrice(dataStore.getUint(\n keccak256(abi.encode(key, TRIGGER_PRICE))\n ));\n\n order.setAcceptablePrice(dataStore.getUint(\n keccak256(abi.encode(key, ACCEPTABLE_PRICE))\n ));\n\n order.setExecutionFee(dataStore.getUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n ));\n\n order.setCallbackGasLimit(dataStore.getUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n ));\n\n order.setMinOutputAmount(dataStore.getUint(\n keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT))\n ));\n\n order.setValidFromTime(dataStore.getUint(\n keccak256(abi.encode(key, VALID_FROM_TIME))\n ));\n\n order.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n order.setSrcChainId(dataStore.getUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n ));\n\n order.setIsLong(dataStore.getBool(\n keccak256(abi.encode(key, IS_LONG))\n ));\n\n order.setShouldUnwrapNativeToken(dataStore.getBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n ));\n\n order.setIsFrozen(dataStore.getBool(\n keccak256(abi.encode(key, IS_FROZEN))\n ));\n\n order.setAutoCancel(dataStore.getBool(\n keccak256(abi.encode(key, AUTO_CANCEL))\n ));\n\n order.setDataList(dataStore.getBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n ));\n\n return order;\n }\n\n function set(DataStore dataStore, bytes32 key, Order.Props memory order) external {\n dataStore.addBytes32(\n Keys.ORDER_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountOrderListKey(order.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n order.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, RECEIVER)),\n order.receiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CANCELLATION_RECEIVER)),\n order.cancellationReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT)),\n order.callbackContract()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER)),\n order.uiFeeReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET)),\n order.market()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN)),\n order.initialCollateralToken()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, SWAP_PATH)),\n order.swapPath()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, ORDER_TYPE)),\n uint256(order.orderType())\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE)),\n uint256(order.decreasePositionSwapType())\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SIZE_DELTA_USD)),\n order.sizeDeltaUsd()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT)),\n order.initialCollateralDeltaAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, TRIGGER_PRICE)),\n order.triggerPrice()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, ACCEPTABLE_PRICE)),\n order.acceptablePrice()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, EXECUTION_FEE)),\n order.executionFee()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),\n order.callbackGasLimit()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT)),\n order.minOutputAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, VALID_FROM_TIME)),\n order.validFromTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n order.updatedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID)),\n order.srcChainId()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, IS_LONG)),\n order.isLong()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),\n order.shouldUnwrapNativeToken()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, IS_FROZEN)),\n order.isFrozen()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, AUTO_CANCEL)),\n order.autoCancel()\n );\n\n dataStore.setBytes32Array(\n keccak256(abi.encode(key, DATA_LIST)),\n order.dataList()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) {\n revert Errors.OrderNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.ORDER_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountOrderListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CANCELLATION_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, SWAP_PATH))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, ORDER_TYPE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SIZE_DELTA_USD))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, TRIGGER_PRICE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, ACCEPTABLE_PRICE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, VALID_FROM_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, IS_LONG))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, IS_FROZEN))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, AUTO_CANCEL))\n );\n\n dataStore.removeBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n );\n }\n\n function getOrderCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.ORDER_LIST);\n }\n\n function getOrderKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end);\n }\n\n function getAccountOrderCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountOrderListKey(account));\n }\n\n function getAccountOrderKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountOrderListKey(account), start, end);\n }\n}\n" + }, + "contracts/order/OrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./AutoCancelUtils.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\n\nimport \"./Order.sol\";\nimport \"./OrderVault.sol\";\nimport \"./OrderStoreUtils.sol\";\nimport \"./OrderEventUtils.sol\";\n\nimport \"../nonce/NonceUtils.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"./BaseOrderUtils.sol\";\nimport \"./IBaseOrderUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\n\nimport \"../utils/Array.sol\";\nimport \"../utils/AccountUtils.sol\";\nimport \"../referral/ReferralUtils.sol\";\nimport \"../multichain/MultichainUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\n\n// @title OrderUtils\n// @dev Library for order functions\nlibrary OrderUtils {\n using Order for Order.Props;\n using Position for Position.Props;\n using Price for Price.Props;\n using Array for uint256[];\n\n struct CancelOrderParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n OrderVault orderVault;\n bytes32 key;\n address keeper;\n uint256 startingGas;\n bool isExternalCall;\n bool isAutoCancel;\n string reason;\n bytes reasonBytes;\n }\n\n struct CreateOrderCache {\n bool shouldRecordSeparateExecutionFeeTransfer;\n address wnt;\n uint256 initialCollateralDeltaAmount;\n uint256 estimatedGasLimit;\n uint256 oraclePriceCount;\n uint256 executionFeeDiff;\n }\n\n // @dev creates an order in the order store\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param orderVault OrderVault\n // @param referralStorage ReferralStorage\n // @param account the order account\n // @param srcChainId the source chain id\n // @param params IBaseOrderUtils.CreateOrderParams\n // @param shouldCapMaxExecutionFee whether to cap the max execution fee\n function createOrder(\n DataStore dataStore,\n EventEmitter eventEmitter,\n OrderVault orderVault,\n IReferralStorage referralStorage,\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams memory params,\n bool shouldCapMaxExecutionFee\n ) external returns (bytes32) {\n AccountUtils.validateAccount(account);\n\n ReferralUtils.setTraderReferralCode(referralStorage, account, params.referralCode);\n\n CreateOrderCache memory cache;\n\n cache.wnt = TokenUtils.wnt(dataStore);\n cache.shouldRecordSeparateExecutionFeeTransfer = true;\n\n if (\n params.orderType == Order.OrderType.MarketSwap ||\n params.orderType == Order.OrderType.LimitSwap ||\n params.orderType == Order.OrderType.MarketIncrease ||\n params.orderType == Order.OrderType.LimitIncrease ||\n params.orderType == Order.OrderType.StopIncrease\n ) {\n // for swaps and increase orders, the initialCollateralDeltaAmount is set based on the amount of tokens\n // transferred to the orderVault\n cache.initialCollateralDeltaAmount = orderVault.recordTransferIn(params.addresses.initialCollateralToken);\n if (params.addresses.initialCollateralToken == cache.wnt) {\n if (cache.initialCollateralDeltaAmount < params.numbers.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(\n cache.initialCollateralDeltaAmount,\n params.numbers.executionFee\n );\n }\n cache.initialCollateralDeltaAmount -= params.numbers.executionFee;\n cache.shouldRecordSeparateExecutionFeeTransfer = false;\n }\n } else if (\n params.orderType == Order.OrderType.MarketDecrease ||\n params.orderType == Order.OrderType.LimitDecrease ||\n params.orderType == Order.OrderType.StopLossDecrease\n ) {\n // for decrease orders, the initialCollateralDeltaAmount is based on the passed in value\n cache.initialCollateralDeltaAmount = params.numbers.initialCollateralDeltaAmount;\n } else {\n revert Errors.OrderTypeCannotBeCreated(uint256(params.orderType));\n }\n\n if (cache.shouldRecordSeparateExecutionFeeTransfer) {\n uint256 wntAmount = orderVault.recordTransferIn(cache.wnt);\n if (wntAmount < params.numbers.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.numbers.executionFee);\n }\n\n params.numbers.executionFee = wntAmount;\n }\n\n if (Order.isPositionOrder(params.orderType)) {\n MarketUtils.validatePositionMarket(dataStore, params.addresses.market);\n } else {\n if (params.addresses.market != address(0)) {\n revert Errors.UnexpectedMarket();\n }\n }\n\n if (Order.isMarketOrder(params.orderType) && params.numbers.validFromTime != 0) {\n revert Errors.UnexpectedValidFromTime(uint256(params.orderType));\n }\n\n // validate swap path markets\n MarketUtils.validateSwapPath(dataStore, params.addresses.swapPath);\n\n Order.Props memory order;\n\n order.setAccount(account);\n order.setReceiver(params.addresses.receiver);\n order.setCancellationReceiver(params.addresses.cancellationReceiver);\n order.setCallbackContract(params.addresses.callbackContract);\n order.setMarket(params.addresses.market);\n order.setInitialCollateralToken(params.addresses.initialCollateralToken);\n order.setUiFeeReceiver(params.addresses.uiFeeReceiver);\n order.setSwapPath(params.addresses.swapPath);\n order.setOrderType(params.orderType);\n order.setDecreasePositionSwapType(params.decreasePositionSwapType);\n order.setSizeDeltaUsd(params.numbers.sizeDeltaUsd);\n order.setInitialCollateralDeltaAmount(cache.initialCollateralDeltaAmount);\n order.setTriggerPrice(params.numbers.triggerPrice);\n order.setAcceptablePrice(params.numbers.acceptablePrice);\n order.setCallbackGasLimit(params.numbers.callbackGasLimit);\n order.setMinOutputAmount(params.numbers.minOutputAmount);\n order.setValidFromTime(params.numbers.validFromTime);\n order.setSrcChainId(srcChainId);\n order.setIsLong(params.isLong);\n order.setShouldUnwrapNativeToken(params.shouldUnwrapNativeToken);\n order.setAutoCancel(params.autoCancel);\n order.setDataList(params.dataList);\n\n AccountUtils.validateReceiver(order.receiver());\n if (order.cancellationReceiver() == address(orderVault)) {\n // revert as funds cannot be sent back to the order vault\n revert Errors.InvalidReceiver(order.cancellationReceiver());\n }\n\n CallbackUtils.validateCallbackGasLimit(dataStore, order.callbackGasLimit());\n\n cache.estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order);\n cache.oraclePriceCount = GasUtils.estimateOrderOraclePriceCount(params.addresses.swapPath.length);\n uint256 executionFee;\n (executionFee, cache.executionFeeDiff) = GasUtils.validateAndCapExecutionFee(\n dataStore,\n cache.estimatedGasLimit,\n params.numbers.executionFee,\n cache.oraclePriceCount,\n shouldCapMaxExecutionFee\n );\n order.setExecutionFee(executionFee);\n\n if (cache.executionFeeDiff != 0) {\n GasUtils.transferExcessiveExecutionFee(dataStore, eventEmitter, orderVault, order.account(), cache.executionFeeDiff);\n }\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n\n order.touch();\n\n BaseOrderUtils.validateNonEmptyOrder(order);\n OrderStoreUtils.set(dataStore, key, order);\n\n updateAutoCancelList(dataStore, key, order, order.autoCancel());\n validateTotalCallbackGasLimitForAutoCancelOrders(dataStore, order);\n\n _updatePositionLastSrcChainId(dataStore, order);\n\n OrderEventUtils.emitOrderCreated(eventEmitter, key, order);\n\n return key;\n }\n\n function _updatePositionLastSrcChainId(\n DataStore dataStore,\n Order.Props memory order\n ) private {\n if (Order.isSwapOrder(order.orderType())) {\n return;\n }\n address collateralToken = order.initialCollateralToken();\n\n if (Order.isIncreaseOrder(order.orderType())) {\n collateralToken = SwapUtils.getOutputToken(\n dataStore,\n order.swapPath(),\n order.initialCollateralToken()\n );\n }\n\n bytes32 positionKey = Position.getPositionKey(order.account(), order.market(), collateralToken, order.isLong());\n dataStore.setUint(Keys.positionLastSrcChainId(positionKey), order.srcChainId());\n }\n\n struct CancelOrderCache {\n uint256 gas;\n uint256 minHandleExecutionErrorGas;\n address executionFeeReceiver;\n }\n\n function cancelOrder(CancelOrderParams memory params) public {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n if (params.isExternalCall) {\n params.startingGas -= gasleft() / 63;\n }\n\n CancelOrderCache memory cache;\n\n cache.gas = gasleft();\n cache.minHandleExecutionErrorGas = GasUtils.getMinHandleExecutionErrorGas(params.dataStore);\n\n if (cache.gas < cache.minHandleExecutionErrorGas) {\n if (params.isAutoCancel) {\n revert Errors.InsufficientGasForAutoCancellation(cache.gas, cache.minHandleExecutionErrorGas);\n } else {\n revert Errors.InsufficientGasForCancellation(cache.gas, cache.minHandleExecutionErrorGas);\n }\n }\n\n Order.Props memory order = OrderStoreUtils.get(params.dataStore, params.key);\n BaseOrderUtils.validateNonEmptyOrder(order);\n\n // this could happen if the order was created in new contracts that support new order types\n // but the order is being cancelled in old contracts\n if (!Order.isSupportedOrder(order.orderType())) {\n if (params.isAutoCancel) {\n revert Errors.UnsupportedOrderTypeForAutoCancellation(uint256(order.orderType()));\n } else {\n revert Errors.UnsupportedOrderType(uint256(order.orderType()));\n }\n }\n\n OrderStoreUtils.remove(params.dataStore, params.key, order.account());\n\n if (Order.isIncreaseOrder(order.orderType()) || Order.isSwapOrder(order.orderType())) {\n if (order.initialCollateralDeltaAmount() > 0) {\n address cancellationReceiver = order.cancellationReceiver();\n if (cancellationReceiver == address(0)) {\n cancellationReceiver = order.account();\n }\n\n if (order.srcChainId() == 0) {\n params.orderVault.transferOut(\n order.initialCollateralToken(),\n cancellationReceiver,\n order.initialCollateralDeltaAmount(),\n order.shouldUnwrapNativeToken()\n );\n } else {\n params.orderVault.transferOut(\n order.initialCollateralToken(),\n address(params.multichainVault), // receiver\n order.initialCollateralDeltaAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n order.initialCollateralToken(),\n cancellationReceiver,\n 0 // srcChainId is the current block.chainId\n );\n }\n }\n }\n\n updateAutoCancelList(params.dataStore, params.key, order, false);\n\n OrderEventUtils.emitOrderCancelled(\n params.eventEmitter,\n params.key,\n order.account(),\n params.reason,\n params.reasonBytes\n );\n\n address executionFeeReceiver = order.cancellationReceiver();\n\n if (executionFeeReceiver == address(0)) {\n executionFeeReceiver = order.receiver();\n }\n\n {\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterOrderCancellation(params.key, order, eventData);\n }\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.orderVault\n ),\n params.key,\n order.callbackContract(),\n order.executionFee(),\n params.startingGas,\n GasUtils.estimateOrderOraclePriceCount(order.swapPath().length),\n params.keeper,\n executionFeeReceiver,\n order.srcChainId()\n );\n }\n\n // @dev freezes an order\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param orderVault OrderVault\n // @param key the key of the order to freeze\n // @param keeper the keeper sending the transaction\n // @param startingGas the starting gas of the transaction\n // @param reason the reason the order was frozen\n function freezeOrder(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n OrderVault orderVault,\n bytes32 key,\n address keeper,\n uint256 startingGas,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n startingGas -= gasleft() / 63;\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n BaseOrderUtils.validateNonEmptyOrder(order);\n\n if (order.isFrozen()) {\n revert Errors.OrderAlreadyFrozen();\n }\n\n uint256 executionFee = order.executionFee();\n\n order.setExecutionFee(0);\n order.setIsFrozen(true);\n OrderStoreUtils.set(dataStore, key, order);\n\n OrderEventUtils.emitOrderFrozen(eventEmitter, key, order.account(), reason, reasonBytes);\n\n {\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterOrderFrozen(key, order, eventData);\n }\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n dataStore,\n eventEmitter,\n multichainVault,\n orderVault\n ),\n key,\n order.callbackContract(),\n executionFee,\n startingGas,\n GasUtils.estimateOrderOraclePriceCount(order.swapPath().length),\n keeper,\n order.receiver(),\n order.srcChainId()\n );\n }\n\n function clearAutoCancelOrders(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n OrderVault orderVault,\n bytes32 positionKey,\n address keeper\n ) internal {\n bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey);\n\n for (uint256 i; i < orderKeys.length; i++) {\n cancelOrder(\n CancelOrderParams(\n dataStore,\n eventEmitter,\n multichainVault,\n orderVault,\n orderKeys[i],\n keeper, // keeper\n gasleft(), // startingGas\n false, // isExternalCall\n true, // isAutoCancel\n \"AUTO_CANCEL\", // reason\n \"\" // reasonBytes\n )\n );\n }\n }\n\n function updateAutoCancelList(\n DataStore dataStore,\n bytes32 orderKey,\n Order.Props memory order,\n bool shouldAdd\n ) internal {\n if (\n order.orderType() != Order.OrderType.LimitDecrease && order.orderType() != Order.OrderType.StopLossDecrease\n ) {\n return;\n }\n\n bytes32 positionKey = BaseOrderUtils.getPositionKey(order);\n\n if (shouldAdd) {\n AutoCancelUtils.addAutoCancelOrderKey(dataStore, positionKey, orderKey);\n } else {\n AutoCancelUtils.removeAutoCancelOrderKey(dataStore, positionKey, orderKey);\n }\n }\n\n function validateTotalCallbackGasLimitForAutoCancelOrders(\n DataStore dataStore,\n Order.Props memory order\n ) internal view {\n if (\n order.orderType() != Order.OrderType.LimitDecrease && order.orderType() != Order.OrderType.StopLossDecrease\n ) {\n return;\n }\n\n bytes32 positionKey = BaseOrderUtils.getPositionKey(order);\n uint256 maxTotal = dataStore.getUint(Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS);\n uint256 total = getTotalCallbackGasLimitForAutoCancelOrders(dataStore, positionKey);\n\n if (total > maxTotal) {\n revert Errors.MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(total, maxTotal);\n }\n }\n\n function getTotalCallbackGasLimitForAutoCancelOrders(\n DataStore dataStore,\n bytes32 positionKey\n ) internal view returns (uint256) {\n bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey);\n\n uint256 total;\n\n for (uint256 i; i < orderKeys.length; i++) {\n total += dataStore.getUint(keccak256(abi.encode(orderKeys[i], OrderStoreUtils.CALLBACK_GAS_LIMIT)));\n }\n\n return total;\n }\n}\n" + }, + "contracts/order/OrderVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/StrictBank.sol\";\n\n// @title OrderVault\n// @dev Vault for orders\ncontract OrderVault is StrictBank {\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\n}\n" + }, + "contracts/order/SwapOrderExecutor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../exchange/IOrderExecutor.sol\";\nimport \"./SwapOrderUtils.sol\";\n\ncontract SwapOrderExecutor is ReentrancyGuard, RoleModule {\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) external nonReentrant onlyController returns (EventUtils.EventLogData memory) {\n return SwapOrderUtils.processOrder(params);\n }\n}\n" + }, + "contracts/order/SwapOrderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseOrderUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\nimport \"../multichain/MultichainUtils.sol\";\n\n// @title SwapOrderUtils\n// @dev Library for functions to help with processing a swap order\nlibrary SwapOrderUtils {\n using Order for Order.Props;\n using Array for uint256[];\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // @dev process a swap order\n // @param params BaseOrderUtils.ExecuteOrderParams\n function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {\n if (params.order.market() != address(0)) {\n revert Errors.UnexpectedMarket();\n }\n\n if (params.minOracleTimestamp < params.order.updatedAtTime()) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(\n params.minOracleTimestamp,\n params.order.updatedAtTime()\n );\n }\n\n if (\n !Order.isMarketOrder(params.order.orderType()) &&\n params.minOracleTimestamp < params.order.validFromTime()\n ) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(\n params.minOracleTimestamp,\n params.order.validFromTime()\n );\n }\n\n uint256 requestExpirationTime = params.contracts.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);\n\n if (\n params.order.orderType() == Order.OrderType.MarketSwap &&\n params.maxOracleTimestamp > params.order.updatedAtTime() + requestExpirationTime\n ) {\n revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(\n params.maxOracleTimestamp,\n params.order.updatedAtTime(),\n requestExpirationTime\n );\n }\n\n (address outputToken, uint256 outputAmount) = params.contracts.swapHandler.swap(ISwapUtils.SwapParams(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.oracle,\n params.contracts.orderVault,\n params.key,\n params.order.initialCollateralToken(),\n params.order.initialCollateralDeltaAmount(),\n params.swapPathMarkets,\n params.order.minOutputAmount(),\n params.order.srcChainId() == 0 ? params.order.receiver(): address(params.contracts.multichainVault),\n params.order.uiFeeReceiver(),\n params.order.srcChainId() == 0 ? params.order.shouldUnwrapNativeToken() : false,\n ISwapPricingUtils.SwapPricingType.Swap\n ));\n\n if (params.order.srcChainId() != 0) {\n MultichainUtils.recordTransferIn(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.multichainVault,\n outputToken,\n params.order.receiver(),\n params.order.srcChainId()\n );\n }\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"outputToken\", outputToken);\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"outputAmount\", outputAmount);\n return eventData;\n }\n}\n" + }, + "contracts/position/DecreasePositionCollateralUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"../pricing/PositionPricingUtils.sol\";\n\nimport \"./Position.sol\";\nimport \"./PositionEventUtils.sol\";\nimport \"./PositionUtils.sol\";\nimport \"../order/OrderEventUtils.sol\";\nimport \"../utils/Precision.sol\";\nimport \"../fee/FeeUtils.sol\";\n\nimport \"./DecreasePositionSwapUtils.sol\";\n\n// @title DecreasePositionCollateralUtils\n// @dev Library for functions to help with the calculations when decreasing a position\nlibrary DecreasePositionCollateralUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n\n using Position for Position.Props;\n using Order for Order.Props;\n using Price for Price.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n struct ProcessCollateralCache {\n bool isInsolventCloseAllowed;\n bool wasSwapped;\n uint256 swapOutputAmount;\n PayForCostResult result;\n bool balanceWasImproved;\n }\n\n struct PayForCostResult {\n uint256 amountPaidInCollateralToken;\n uint256 amountPaidInSecondaryOutputToken;\n uint256 remainingCostUsd;\n }\n\n // @dev handle the collateral changes of the position\n // @param params PositionUtils.UpdatePositionParams\n // @param cache DecreasePositionCache\n // @return (PositionUtils.DecreasePositionCollateralValues, PositionPricingUtils.PositionFees)\n function processCollateral(\n PositionUtils.UpdatePositionParams memory params,\n PositionUtils.DecreasePositionCache memory cache\n ) external returns (\n PositionUtils.DecreasePositionCollateralValues memory,\n PositionPricingUtils.PositionFees memory\n ) {\n ProcessCollateralCache memory collateralCache;\n PositionUtils.DecreasePositionCollateralValues memory values;\n\n values.output.outputToken = params.position.collateralToken();\n values.output.secondaryOutputToken = cache.pnlToken;\n\n // only allow insolvent closing if it is a liquidation or ADL order\n // isInsolventCloseAllowed is used in handleEarlyReturn to determine\n // whether the txn should revert if the remainingCostUsd is below zero\n //\n // for isInsolventCloseAllowed to be true, the sizeDeltaUsd must equal\n // the position size, otherwise there may be pending positive pnl that\n // could be used to pay for fees and the position would be undercharged\n // if the position is not fully closed\n //\n // for ADLs it may be possible that a position needs to be closed by a larger\n // size to fully pay for fees, but closing by that larger size could cause a PnlOvercorrected\n // error to be thrown in AdlHandler, this case should be rare\n collateralCache.isInsolventCloseAllowed =\n params.order.sizeDeltaUsd() == params.position.sizeInUsd() &&\n (\n Order.isLiquidationOrder(params.order.orderType()) ||\n params.secondaryOrderType == Order.SecondaryOrderType.Adl\n );\n\n (values.priceImpactUsd, values.executionPrice, collateralCache.balanceWasImproved) = PositionUtils.getExecutionPriceForDecrease(params, cache.prices.indexTokenPrice);\n\n // the totalPositionPnl is calculated based on the current indexTokenPrice instead of the executionPrice\n // since the executionPrice factors in price impact which should be accounted for separately\n // the sizeDeltaInTokens is calculated as position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd()\n // the basePnlUsd is the pnl to be realized, and is calculated as:\n // totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens()\n (values.basePnlUsd, values.uncappedBasePnlUsd, values.sizeDeltaInTokens) = PositionUtils.getPositionPnlUsd(\n params.contracts.dataStore,\n params.market,\n cache.prices,\n params.position,\n params.order.sizeDeltaUsd()\n );\n\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\n params.contracts.dataStore, // dataStore\n params.contracts.referralStorage, // referralStorage\n params.position, // position\n cache.collateralTokenPrice, // collateralTokenPrice\n collateralCache.balanceWasImproved, // balanceWasImproved\n params.market.longToken, // longToken\n params.market.shortToken, // shortToken\n params.order.sizeDeltaUsd(), // sizeDeltaUsd\n params.order.uiFeeReceiver(), // uiFeeReceiver\n Order.isLiquidationOrder(params.order.orderType()) // isLiquidation\n );\n\n // if the pnl is positive, deduct the pnl amount from the pool\n if (values.basePnlUsd > 0) {\n // use pnlTokenPrice.max to minimize the tokens paid out\n uint256 deductionAmountForPool = values.basePnlUsd.toUint256() / cache.pnlTokenPrice.max;\n\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n cache.pnlToken,\n -deductionAmountForPool.toInt256()\n );\n\n if (values.output.outputToken == cache.pnlToken) {\n values.output.outputAmount += deductionAmountForPool;\n } else {\n values.output.secondaryOutputAmount += deductionAmountForPool;\n }\n }\n\n // order size has been enforced to be less or equal than position size (i.e. sizeDeltaUsd <= sizeInUsd)\n (values.proportionalPendingImpactAmount, values.proportionalPendingImpactUsd) = _getProportionalPendingImpactValues(\n params.position.sizeInUsd(),\n params.position.pendingImpactAmount(),\n params.order.sizeDeltaUsd(),\n cache.prices.indexTokenPrice\n );\n\n values.totalImpactUsd = values.proportionalPendingImpactUsd + values.priceImpactUsd;\n\n if (values.totalImpactUsd < 0) {\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactor(\n params.contracts.dataStore,\n params.market.marketToken,\n false\n );\n\n // convert the max price impact to the min negative value\n // e.g. if sizeDeltaUsd is 10,000 and maxPriceImpactFactor is 2%\n // then minPriceImpactUsd = -200\n int256 minPriceImpactUsd = -Precision.applyFactor(params.order.sizeDeltaUsd(), maxPriceImpactFactor).toInt256();\n\n // cap totalImpactUsd to the min negative value and store the difference in priceImpactDiffUsd\n // e.g. if totalImpactUsd is -500 and minPriceImpactUsd is -200\n // then set priceImpactDiffUsd to -200 - -500 = 300\n // set totalImpactUsd to -200\n if (values.totalImpactUsd < minPriceImpactUsd) {\n values.priceImpactDiffUsd = (minPriceImpactUsd - values.totalImpactUsd).toUint256();\n values.totalImpactUsd = minPriceImpactUsd;\n }\n }\n\n values.totalImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\n params.contracts.dataStore,\n params.market.marketToken,\n values.totalImpactUsd,\n params.order.sizeDeltaUsd()\n );\n\n // cap the positive totalImpactUsd by the available amount in the position impact pool\n values.totalImpactUsd = MarketUtils.capPositiveImpactUsdByPositionImpactPool(\n params.contracts.dataStore,\n params.market,\n cache.prices,\n values.totalImpactUsd\n );\n\n if (values.totalImpactUsd > 0) {\n uint256 deductionAmountForImpactPool = Calc.roundUpDivision(values.totalImpactUsd.toUint256(), cache.prices.indexTokenPrice.min);\n\n MarketUtils.applyDeltaToPositionImpactPool(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n -deductionAmountForImpactPool.toInt256()\n );\n\n // use pnlTokenPrice.max to minimize the payout from the pool\n // some impact pool value may be transferred to the market token pool if there is a\n // large spread between min and max prices\n // since if there is a positive priceImpactUsd, the impact pool would be reduced using indexTokenPrice.min to\n // maximize the deduction value, while the market token pool is reduced using the pnlTokenPrice.max to minimize\n // the deduction value\n // the pool value is calculated by subtracting the worth of the tokens in the position impact pool\n // so this transfer of value would increase the price of the market token\n uint256 deductionAmountForPool = values.totalImpactUsd.toUint256() / cache.pnlTokenPrice.max;\n\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n cache.pnlToken,\n -deductionAmountForPool.toInt256()\n );\n\n if (values.output.outputToken == cache.pnlToken) {\n values.output.outputAmount += deductionAmountForPool;\n } else {\n values.output.secondaryOutputAmount += deductionAmountForPool;\n }\n }\n\n // swap profit to the collateral token\n // if the decreasePositionSwapType was set to NoSwap or if the swap fails due\n // to insufficient liquidity or other reasons then it is possible that\n // the profit remains in a different token from the collateral token\n (collateralCache.wasSwapped, collateralCache.swapOutputAmount) = DecreasePositionSwapUtils.swapProfitToCollateralToken(\n params,\n cache.pnlToken,\n values.output.secondaryOutputAmount\n );\n\n // if the swap was successful the profit should have been swapped\n // to the collateral token\n if (collateralCache.wasSwapped) {\n values.output.outputAmount += collateralCache.swapOutputAmount;\n values.output.secondaryOutputAmount = 0;\n }\n\n values.remainingCollateralAmount = params.position.collateralAmount();\n\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(\n getPositionFeesParams\n );\n\n // pay for funding fees\n (values, collateralCache.result) = payForCost(\n params,\n values,\n cache.prices,\n cache.collateralTokenPrice,\n // use collateralTokenPrice.min because the payForCost\n // will divide the USD value by the price.min as well\n fees.funding.fundingFeeAmount * cache.collateralTokenPrice.min\n );\n\n if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {\n address holdingAddress = params.contracts.dataStore.getAddress(Keys.HOLDING_ADDRESS);\n if (holdingAddress == address(0)) {\n revert Errors.EmptyHoldingAddress();\n }\n\n // send the funding fee amount to the holding address\n // this funding fee amount should be swapped to the required token\n // and the resulting tokens should be deposited back into the pool\n MarketUtils.incrementClaimableCollateralAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n values.output.secondaryOutputToken,\n holdingAddress,\n collateralCache.result.amountPaidInSecondaryOutputToken\n );\n }\n\n if (collateralCache.result.amountPaidInCollateralToken < fees.funding.fundingFeeAmount) {\n // the case where this is insufficient collateral to pay funding fees\n // should be rare, and the difference should be small\n // in case it happens, the pool should be topped up with the required amount using\n // the claimable amount sent to the holding address, an insurance fund, or similar mechanism\n PositionEventUtils.emitInsufficientFundingFeePayment(\n params.contracts.eventEmitter,\n params.market.marketToken,\n params.position.collateralToken(),\n fees.funding.fundingFeeAmount,\n collateralCache.result.amountPaidInCollateralToken,\n collateralCache.result.amountPaidInSecondaryOutputToken\n );\n }\n\n if (collateralCache.result.remainingCostUsd > 0) {\n return handleEarlyReturn(\n params,\n values,\n fees,\n collateralCache,\n \"funding\"\n );\n }\n\n // pay for negative pnl\n if (values.basePnlUsd < 0) {\n (values, collateralCache.result) = payForCost(\n params,\n values,\n cache.prices,\n cache.collateralTokenPrice,\n (-values.basePnlUsd).toUint256()\n );\n\n if (collateralCache.result.amountPaidInCollateralToken > 0) {\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n params.position.collateralToken(),\n collateralCache.result.amountPaidInCollateralToken.toInt256()\n );\n }\n\n if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n values.output.secondaryOutputToken,\n collateralCache.result.amountPaidInSecondaryOutputToken.toInt256()\n );\n }\n\n if (collateralCache.result.remainingCostUsd > 0) {\n return handleEarlyReturn(\n params,\n values,\n fees,\n collateralCache,\n \"pnl\"\n );\n }\n }\n\n // pay for fees\n (values, collateralCache.result) = payForCost(\n params,\n values,\n cache.prices,\n cache.collateralTokenPrice,\n // use collateralTokenPrice.min because the payForCost\n // will divide the USD value by the price.min as well\n fees.totalCostAmountExcludingFunding * cache.collateralTokenPrice.min\n );\n\n // if fees were fully paid in the collateral token, update the pool and claimable fee amounts\n if (collateralCache.result.remainingCostUsd == 0 && collateralCache.result.amountPaidInSecondaryOutputToken == 0) {\n // there may be a large amount of borrowing fees that could have been accumulated\n // these fees could cause the pool to become unbalanced, price impact is not paid for causing\n // this imbalance\n // the swap impact pool should be built up so that it can be used to pay for positive price impact\n // for re-balancing to help handle this case\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n params.position.collateralToken(),\n fees.feeAmountForPool.toInt256()\n );\n\n FeeUtils.incrementClaimableFeeAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n params.position.collateralToken(),\n fees.feeReceiverAmount,\n Keys.POSITION_FEE_TYPE\n );\n\n FeeUtils.incrementClaimableUiFeeAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.order.uiFeeReceiver(),\n params.market.marketToken,\n params.position.collateralToken(),\n fees.ui.uiFeeAmount,\n Keys.UI_POSITION_FEE_TYPE\n );\n } else {\n // the fees are expected to be paid in the collateral token\n // if there are insufficient funds to pay for fees entirely in the collateral token\n // then credit the fee amount entirely to the pool\n if (collateralCache.result.amountPaidInCollateralToken > 0) {\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n params.position.collateralToken(),\n collateralCache.result.amountPaidInCollateralToken.toInt256()\n );\n }\n\n if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n values.output.secondaryOutputToken,\n collateralCache.result.amountPaidInSecondaryOutputToken.toInt256()\n );\n }\n\n // empty the fees since the amount was entirely paid to the pool instead of for fees\n // it is possible for the txn execution to still complete even in this case\n // as long as the remainingCostUsd is still zero\n fees = getEmptyFees(fees);\n }\n\n if (collateralCache.result.remainingCostUsd > 0) {\n return handleEarlyReturn(\n params,\n values,\n fees,\n collateralCache,\n \"fees\"\n );\n }\n\n // pay for negative price impact\n if (values.totalImpactUsd < 0) {\n (values, collateralCache.result) = payForCost(\n params,\n values,\n cache.prices,\n cache.collateralTokenPrice,\n (-values.totalImpactUsd).toUint256()\n );\n\n if (collateralCache.result.amountPaidInCollateralToken > 0) {\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n params.position.collateralToken(),\n collateralCache.result.amountPaidInCollateralToken.toInt256()\n );\n\n MarketUtils.applyDeltaToPositionImpactPool(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n (collateralCache.result.amountPaidInCollateralToken * cache.collateralTokenPrice.min / cache.prices.indexTokenPrice.max).toInt256()\n );\n }\n\n if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n values.output.secondaryOutputToken,\n collateralCache.result.amountPaidInSecondaryOutputToken.toInt256()\n );\n\n MarketUtils.applyDeltaToPositionImpactPool(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n (collateralCache.result.amountPaidInSecondaryOutputToken * cache.pnlTokenPrice.min / cache.prices.indexTokenPrice.max).toInt256()\n );\n }\n\n if (collateralCache.result.remainingCostUsd > 0) {\n return handleEarlyReturn(\n params,\n values,\n fees,\n collateralCache,\n \"impact\"\n );\n }\n }\n\n // pay for price impact diff\n if (values.priceImpactDiffUsd > 0) {\n (values, collateralCache.result) = payForCost(\n params,\n values,\n cache.prices,\n cache.collateralTokenPrice,\n values.priceImpactDiffUsd\n );\n\n if (collateralCache.result.amountPaidInCollateralToken > 0) {\n MarketUtils.incrementClaimableCollateralAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n params.position.collateralToken(),\n params.order.account(),\n collateralCache.result.amountPaidInCollateralToken\n );\n }\n\n if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {\n MarketUtils.incrementClaimableCollateralAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n values.output.secondaryOutputToken,\n params.order.account(),\n collateralCache.result.amountPaidInSecondaryOutputToken\n );\n }\n\n if (collateralCache.result.remainingCostUsd > 0) {\n return handleEarlyReturn(\n params,\n values,\n fees,\n collateralCache,\n \"diff\"\n );\n }\n }\n\n // the priceImpactDiffUsd has been deducted from the output amount or the position's collateral\n // to reduce the chance that the position's collateral is reduced by an unexpected amount, adjust the\n // initialCollateralDeltaAmount by the priceImpactDiffAmount\n // this would also help to prevent the position's leverage from being unexpectedly increased\n //\n // note that this calculation may not be entirely accurate since it is possible that the priceImpactDiffUsd\n // could have been paid with one of or a combination of collateral / outputAmount / secondaryOutputAmount\n if (params.order.initialCollateralDeltaAmount() > 0 && values.priceImpactDiffUsd > 0) {\n uint256 initialCollateralDeltaAmount = params.order.initialCollateralDeltaAmount();\n\n uint256 priceImpactDiffAmount = values.priceImpactDiffUsd / cache.collateralTokenPrice.min;\n if (initialCollateralDeltaAmount > priceImpactDiffAmount) {\n params.order.setInitialCollateralDeltaAmount(initialCollateralDeltaAmount - priceImpactDiffAmount);\n } else {\n params.order.setInitialCollateralDeltaAmount(0);\n }\n\n OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n initialCollateralDeltaAmount, // collateralDeltaAmount\n params.order.initialCollateralDeltaAmount() // nextCollateralDeltaAmount\n );\n }\n\n // cap the withdrawable amount to the remainingCollateralAmount\n if (params.order.initialCollateralDeltaAmount() > values.remainingCollateralAmount) {\n OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n params.order.initialCollateralDeltaAmount(), // collateralDeltaAmount\n values.remainingCollateralAmount // nextCollateralDeltaAmount\n );\n\n params.order.setInitialCollateralDeltaAmount(values.remainingCollateralAmount);\n }\n\n if (params.order.initialCollateralDeltaAmount() > 0) {\n values.remainingCollateralAmount -= params.order.initialCollateralDeltaAmount();\n values.output.outputAmount += params.order.initialCollateralDeltaAmount();\n }\n\n return (values, fees);\n }\n\n function payForCost(\n PositionUtils.UpdatePositionParams memory params,\n PositionUtils.DecreasePositionCollateralValues memory values,\n MarketUtils.MarketPrices memory prices,\n Price.Props memory collateralTokenPrice,\n uint256 costUsd\n ) internal pure returns (PositionUtils.DecreasePositionCollateralValues memory, PayForCostResult memory) {\n PayForCostResult memory result;\n\n if (costUsd == 0) { return (values, result); }\n\n uint256 remainingCostInOutputToken = Calc.roundUpDivision(costUsd, collateralTokenPrice.min);\n\n if (values.output.outputAmount > 0) {\n if (values.output.outputAmount > remainingCostInOutputToken) {\n result.amountPaidInCollateralToken += remainingCostInOutputToken;\n values.output.outputAmount -= remainingCostInOutputToken;\n remainingCostInOutputToken = 0;\n } else {\n result.amountPaidInCollateralToken += values.output.outputAmount;\n remainingCostInOutputToken -= values.output.outputAmount;\n values.output.outputAmount = 0;\n }\n }\n\n if (remainingCostInOutputToken == 0) { return (values, result); }\n\n if (values.remainingCollateralAmount > 0) {\n if (values.remainingCollateralAmount > remainingCostInOutputToken) {\n result.amountPaidInCollateralToken += remainingCostInOutputToken;\n values.remainingCollateralAmount -= remainingCostInOutputToken;\n remainingCostInOutputToken = 0;\n } else {\n result.amountPaidInCollateralToken += values.remainingCollateralAmount;\n remainingCostInOutputToken -= values.remainingCollateralAmount;\n values.remainingCollateralAmount = 0;\n }\n }\n\n if (remainingCostInOutputToken == 0) { return (values, result); }\n\n Price.Props memory secondaryOutputTokenPrice = MarketUtils.getCachedTokenPrice(values.output.secondaryOutputToken, params.market, prices);\n\n uint256 remainingCostInSecondaryOutputToken = remainingCostInOutputToken * collateralTokenPrice.min / secondaryOutputTokenPrice.min;\n\n if (values.output.secondaryOutputAmount > 0) {\n if (values.output.secondaryOutputAmount > remainingCostInSecondaryOutputToken) {\n result.amountPaidInSecondaryOutputToken += remainingCostInSecondaryOutputToken;\n values.output.secondaryOutputAmount -= remainingCostInSecondaryOutputToken;\n remainingCostInSecondaryOutputToken = 0;\n } else {\n result.amountPaidInSecondaryOutputToken += values.output.secondaryOutputAmount;\n remainingCostInSecondaryOutputToken -= values.output.secondaryOutputAmount;\n values.output.secondaryOutputAmount = 0;\n }\n }\n\n result.remainingCostUsd = remainingCostInSecondaryOutputToken * secondaryOutputTokenPrice.min;\n\n return (values, result);\n }\n\n function handleEarlyReturn(\n PositionUtils.UpdatePositionParams memory params,\n PositionUtils.DecreasePositionCollateralValues memory values,\n PositionPricingUtils.PositionFees memory fees,\n ProcessCollateralCache memory collateralCache,\n string memory step\n ) internal returns (PositionUtils.DecreasePositionCollateralValues memory, PositionPricingUtils.PositionFees memory) {\n if (!collateralCache.isInsolventCloseAllowed) {\n revert Errors.InsufficientFundsToPayForCosts(collateralCache.result.remainingCostUsd, step);\n }\n\n PositionEventUtils.emitPositionFeesInfo(\n params.contracts.eventEmitter,\n params.orderKey,\n params.positionKey,\n params.market.marketToken,\n params.position.collateralToken(),\n params.order.sizeDeltaUsd(),\n false, // isIncrease\n fees\n );\n\n PositionEventUtils.emitInsolventClose(\n params.contracts.eventEmitter,\n params.orderKey,\n params.position.collateralAmount(),\n values.basePnlUsd,\n collateralCache.result.remainingCostUsd,\n step\n );\n\n return (values, getEmptyFees(fees));\n }\n\n function getEmptyFees(\n PositionPricingUtils.PositionFees memory fees\n ) internal pure returns (PositionPricingUtils.PositionFees memory) {\n PositionPricingUtils.PositionReferralFees memory referral = PositionPricingUtils.PositionReferralFees({\n referralCode: bytes32(0),\n affiliate: address(0),\n trader: address(0),\n totalRebateFactor: 0,\n affiliateRewardFactor: 0,\n adjustedAffiliateRewardFactor: 0,\n traderDiscountFactor: 0,\n totalRebateAmount: 0,\n traderDiscountAmount: 0,\n affiliateRewardAmount: 0\n });\n\n PositionPricingUtils.PositionProFees memory pro = PositionPricingUtils.PositionProFees({\n traderTier: 0,\n traderDiscountFactor: 0,\n traderDiscountAmount: 0\n });\n\n // allow the accumulated funding fees to still be claimable\n // return the latestFundingFeeAmountPerSize, latestLongTokenClaimableFundingAmountPerSize,\n // latestShortTokenClaimableFundingAmountPerSize values as these may be used to update the\n // position's values if the position will be partially closed\n PositionPricingUtils.PositionFundingFees memory funding = PositionPricingUtils.PositionFundingFees({\n fundingFeeAmount: 0,\n claimableLongTokenAmount: fees.funding.claimableLongTokenAmount,\n claimableShortTokenAmount: fees.funding.claimableShortTokenAmount,\n latestFundingFeeAmountPerSize: fees.funding.latestFundingFeeAmountPerSize,\n latestLongTokenClaimableFundingAmountPerSize: fees.funding.latestLongTokenClaimableFundingAmountPerSize,\n latestShortTokenClaimableFundingAmountPerSize: fees.funding.latestShortTokenClaimableFundingAmountPerSize\n });\n\n PositionPricingUtils.PositionBorrowingFees memory borrowing = PositionPricingUtils.PositionBorrowingFees({\n borrowingFeeUsd: 0,\n borrowingFeeAmount: 0,\n borrowingFeeReceiverFactor: 0,\n borrowingFeeAmountForFeeReceiver: 0\n });\n\n PositionPricingUtils.PositionUiFees memory ui = PositionPricingUtils.PositionUiFees({\n uiFeeReceiver: address(0),\n uiFeeReceiverFactor: 0,\n uiFeeAmount: 0\n });\n\n PositionPricingUtils.PositionLiquidationFees memory liquidation = PositionPricingUtils.PositionLiquidationFees({\n liquidationFeeUsd: 0,\n liquidationFeeAmount: 0,\n liquidationFeeReceiverFactor: 0,\n liquidationFeeAmountForFeeReceiver: 0\n });\n\n // all fees are zeroed even though funding may have been paid\n // the funding fee amount value may not be accurate in the events due to this\n PositionPricingUtils.PositionFees memory _fees = PositionPricingUtils.PositionFees({\n referral: referral,\n pro: pro,\n funding: funding,\n borrowing: borrowing,\n ui: ui,\n liquidation: liquidation,\n collateralTokenPrice: fees.collateralTokenPrice,\n positionFeeFactor: 0,\n protocolFeeAmount: 0,\n positionFeeReceiverFactor: 0,\n feeReceiverAmount: 0,\n feeAmountForPool: 0,\n positionFeeAmountForPool: 0,\n positionFeeAmount: 0,\n totalCostAmountExcludingFunding: 0,\n totalCostAmount: 0,\n totalDiscountAmount: 0\n });\n\n return _fees;\n }\n\n function _getProportionalPendingImpactValues(\n uint256 sizeInUsd,\n int256 positionPendingImpactAmount,\n uint256 sizeDeltaUsd,\n Price.Props memory indexTokenPrice\n ) private pure returns (int256, int256) {\n int256 proportionalPendingImpactAmount = Precision.mulDiv(positionPendingImpactAmount, sizeDeltaUsd, sizeInUsd, positionPendingImpactAmount < 0);\n\n // minimize the positive impact, maximize the negative impact\n int256 proportionalPendingImpactUsd = proportionalPendingImpactAmount > 0\n ? proportionalPendingImpactAmount * indexTokenPrice.min.toInt256()\n : proportionalPendingImpactAmount * indexTokenPrice.max.toInt256();\n\n return (proportionalPendingImpactAmount, proportionalPendingImpactUsd);\n }\n}\n" + }, + "contracts/position/DecreasePositionSwapUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./PositionUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\n\nlibrary DecreasePositionSwapUtils {\n using Order for Order.Props;\n using Position for Position.Props;\n\n // swap the withdrawn collateral from collateralToken to pnlToken if needed\n function swapWithdrawnCollateralToPnlToken(\n PositionUtils.UpdatePositionParams memory params,\n PositionUtils.DecreasePositionCollateralValues memory values\n ) external returns (PositionUtils.DecreasePositionCollateralValues memory) {\n if (values.output.outputAmount > 0 && params.order.decreasePositionSwapType() == Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken) {\n Market.Props[] memory swapPathMarkets = new Market.Props[](1);\n swapPathMarkets[0] = params.market;\n\n try params.contracts.swapHandler.swap(\n ISwapUtils.SwapParams(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.oracle,\n Bank(payable(params.market.marketToken)),\n params.orderKey,\n params.position.collateralToken(), // tokenIn\n values.output.outputAmount, // amountIn\n swapPathMarkets, // markets\n 0, // minOutputAmount\n params.market.marketToken, // receiver\n params.order.uiFeeReceiver(), // uiFeeReceiver\n false, // shouldUnwrapNativeToken\n ISwapPricingUtils.SwapPricingType.Swap\n )\n ) returns (address tokenOut, uint256 swapOutputAmount) {\n if (tokenOut != values.output.secondaryOutputToken) {\n revert Errors.InvalidOutputToken(tokenOut, values.output.secondaryOutputToken);\n }\n // combine the values into outputToken and outputAmount\n values.output.outputToken = tokenOut;\n values.output.outputAmount = values.output.secondaryOutputAmount + swapOutputAmount;\n values.output.secondaryOutputAmount = 0;\n } catch Error(string memory reason) {\n emit SwapUtils.SwapReverted(reason, \"\");\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n emit SwapUtils.SwapReverted(reason, reasonBytes);\n }\n }\n\n return values;\n }\n\n // swap the realized profit from the pnlToken to the collateralToken if needed\n function swapProfitToCollateralToken(\n PositionUtils.UpdatePositionParams memory params,\n address pnlToken,\n uint256 profitAmount\n ) external returns (bool, uint256) {\n if (profitAmount > 0 && params.order.decreasePositionSwapType() == Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken) {\n Market.Props[] memory swapPathMarkets = new Market.Props[](1);\n swapPathMarkets[0] = params.market;\n\n try params.contracts.swapHandler.swap(\n ISwapUtils.SwapParams(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.contracts.oracle,\n Bank(payable(params.market.marketToken)),\n params.orderKey,\n pnlToken, // tokenIn\n profitAmount, // amountIn\n swapPathMarkets, // markets\n 0, // minOutputAmount\n params.market.marketToken, // receiver\n params.order.uiFeeReceiver(), // uiFeeReceiver\n false, // shouldUnwrapNativeToken\n ISwapPricingUtils.SwapPricingType.Swap\n )\n ) returns (address /* tokenOut */, uint256 swapOutputAmount) {\n return (true, swapOutputAmount);\n } catch Error(string memory reason) {\n emit SwapUtils.SwapReverted(reason, \"\");\n } catch (bytes memory reasonBytes) {\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);\n emit SwapUtils.SwapReverted(reason, reasonBytes);\n }\n }\n\n return (false, 0);\n }\n}\n" + }, + "contracts/position/DecreasePositionUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Precision.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"../pricing/PositionPricingUtils.sol\";\n\nimport \"./Position.sol\";\nimport \"./PositionStoreUtils.sol\";\nimport \"./PositionUtils.sol\";\nimport \"./PositionEventUtils.sol\";\nimport \"../order/OrderEventUtils.sol\";\n\nimport \"./DecreasePositionCollateralUtils.sol\";\n\n// @title DecreasePositionUtils\n// @dev Library for functions to help with decreasing a position\nlibrary DecreasePositionUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n\n using Position for Position.Props;\n using Order for Order.Props;\n using Price for Price.Props;\n\n // @dev DecreasePositionResult struct for the results of decreasePosition\n // @param outputToken the output token\n // @param outputAmount the output amount\n // @param secondaryOutputToken the secondary output token\n // @param secondaryOutputAmount the secondary output amount\n struct DecreasePositionResult {\n address outputToken;\n uint256 outputAmount;\n address secondaryOutputToken;\n uint256 secondaryOutputAmount;\n uint256 orderSizeDeltaUsd;\n uint256 orderInitialCollateralDeltaAmount;\n }\n\n // @dev decreases a position\n // The decreasePosition function decreases the size of an existing position\n // in a market. It takes a PositionUtils.UpdatePositionParams object as an input, which\n // includes information about the position to be decreased, the market in\n // which the position exists, and the order that is being used to decrease the position.\n //\n // The function first calculates the prices of the tokens in the market, and then\n // checks whether the position is liquidatable based on the current market prices.\n // If the order is a liquidation order and the position is not liquidatable, the function reverts.\n //\n // If there is not enough collateral in the position to complete the decrease,\n // the function reverts. Otherwise, the function updates the position's size and\n // collateral amount, and increments the claimable funding amount for\n // the market if necessary.\n //\n // Finally, the function returns a DecreasePositionResult object containing\n // information about the outcome of the decrease operation, including the amount\n // of collateral removed from the position and any fees that were paid.\n // @param params PositionUtils.UpdatePositionParams\n function decreasePosition(\n PositionUtils.UpdatePositionParams memory params\n ) external returns (DecreasePositionResult memory) {\n PositionUtils.DecreasePositionCache memory cache;\n\n cache.prices = MarketUtils.getMarketPrices(\n params.contracts.oracle,\n params.market\n );\n\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\n params.order.initialCollateralToken(),\n params.market,\n cache.prices\n );\n\n // cap the order size to the position size\n if (params.order.sizeDeltaUsd() > params.position.sizeInUsd()) {\n if (params.order.orderType() == Order.OrderType.LimitDecrease ||\n params.order.orderType() == Order.OrderType.StopLossDecrease) {\n\n OrderEventUtils.emitOrderSizeDeltaAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n params.order.sizeDeltaUsd(),\n params.position.sizeInUsd()\n );\n\n params.order.setSizeDeltaUsd(params.position.sizeInUsd());\n } else {\n revert Errors.InvalidDecreaseOrderSize(params.order.sizeDeltaUsd(), params.position.sizeInUsd());\n }\n }\n\n // cap the initialCollateralDeltaAmount to the position collateralAmount\n if (params.order.initialCollateralDeltaAmount() > params.position.collateralAmount()) {\n OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n params.order.initialCollateralDeltaAmount(),\n params.position.collateralAmount()\n );\n\n params.order.setInitialCollateralDeltaAmount(params.position.collateralAmount());\n }\n\n // if the position will be partially decreased then do a check on the\n // remaining collateral amount and update the order attributes if needed\n if (params.order.sizeDeltaUsd() < params.position.sizeInUsd()) {\n // estimate pnl based on indexTokenPrice\n (cache.estimatedPositionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = PositionUtils.getPositionPnlUsd(\n params.contracts.dataStore,\n params.market,\n cache.prices,\n params.position,\n params.position.sizeInUsd()\n );\n\n cache.estimatedRealizedPnlUsd = Precision.mulDiv(cache.estimatedPositionPnlUsd, params.order.sizeDeltaUsd(), params.position.sizeInUsd());\n cache.estimatedRemainingPnlUsd = cache.estimatedPositionPnlUsd - cache.estimatedRealizedPnlUsd;\n\n PositionUtils.WillPositionCollateralBeSufficientValues memory positionValues = PositionUtils.WillPositionCollateralBeSufficientValues(\n params.position.sizeInUsd() - params.order.sizeDeltaUsd(), // positionSizeInUsd\n params.position.collateralAmount() - params.order.initialCollateralDeltaAmount(), // positionCollateralAmount\n cache.estimatedRealizedPnlUsd, // realizedPnlUsd\n -params.order.sizeDeltaUsd().toInt256() // openInterestDelta\n );\n\n (bool willBeSufficient, int256 estimatedRemainingCollateralUsd) = PositionUtils.willPositionCollateralBeSufficient(\n params.contracts.dataStore,\n params.market,\n cache.prices,\n params.position.collateralToken(),\n params.position.isLong(),\n positionValues\n );\n\n cache.minCollateralUsd = params.contracts.dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\n\n // do not allow withdrawal of collateral if it would lead to the position\n // having an insufficient amount of collateral\n // this helps to prevent gaming by opening a position then reducing collateral\n // to increase the leverage of the position\n //\n // alternatively, if the estimatedRemainingCollateralUsd + estimatedRemainingPnlUsd will be less\n // than minCollateralUsd, then set the initialCollateralDeltaAmount to zero as well\n // in the subsequent check, the position size may be updated to fully close the position\n // due to the above condition, so adding the collateral back here can help avoid the position\n // being fully closed\n if (\n !willBeSufficient ||\n (estimatedRemainingCollateralUsd + cache.estimatedRemainingPnlUsd) < cache.minCollateralUsd\n ) {\n if (params.order.sizeDeltaUsd() == 0) {\n revert Errors.UnableToWithdrawCollateral(estimatedRemainingCollateralUsd);\n }\n\n OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n params.order.initialCollateralDeltaAmount(),\n 0\n );\n\n // the estimatedRemainingCollateralUsd subtracts the initialCollateralDeltaAmount\n // since the initialCollateralDeltaAmount will be set to zero, the initialCollateralDeltaAmount\n // should be added back to the estimatedRemainingCollateralUsd\n estimatedRemainingCollateralUsd += (params.order.initialCollateralDeltaAmount() * cache.collateralTokenPrice.min).toInt256();\n params.order.setInitialCollateralDeltaAmount(0);\n }\n\n // if the remaining collateral including position pnl will be below\n // the min collateral usd value, then close the position\n //\n // if the position has sufficient remaining collateral including pnl\n // then allow the position to be partially closed and the updated\n // position to remain open\n if ((estimatedRemainingCollateralUsd + cache.estimatedRemainingPnlUsd) < cache.minCollateralUsd) {\n OrderEventUtils.emitOrderSizeDeltaAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n params.order.sizeDeltaUsd(),\n params.position.sizeInUsd()\n );\n\n params.order.setSizeDeltaUsd(params.position.sizeInUsd());\n }\n\n if (\n params.position.sizeInUsd() > params.order.sizeDeltaUsd() &&\n params.position.sizeInUsd() - params.order.sizeDeltaUsd() < params.contracts.dataStore.getUint(Keys.MIN_POSITION_SIZE_USD)\n ) {\n OrderEventUtils.emitOrderSizeDeltaAutoUpdated(\n params.contracts.eventEmitter,\n params.orderKey,\n params.order.sizeDeltaUsd(),\n params.position.sizeInUsd()\n );\n\n params.order.setSizeDeltaUsd(params.position.sizeInUsd());\n }\n }\n\n // if the position will be closed, set the initial collateral delta amount\n // to zero to help ensure that the order can be executed\n if (params.order.sizeDeltaUsd() == params.position.sizeInUsd() && params.order.initialCollateralDeltaAmount() > 0) {\n params.order.setInitialCollateralDeltaAmount(0);\n }\n\n cache.pnlToken = params.position.isLong() ? params.market.longToken : params.market.shortToken;\n cache.pnlTokenPrice = params.position.isLong() ? cache.prices.longTokenPrice : cache.prices.shortTokenPrice;\n\n if (params.order.decreasePositionSwapType() != Order.DecreasePositionSwapType.NoSwap &&\n cache.pnlToken == params.position.collateralToken()) {\n params.order.setDecreasePositionSwapType(Order.DecreasePositionSwapType.NoSwap);\n }\n\n if (Order.isLiquidationOrder(params.order.orderType())) {\n (bool isLiquidatable, string memory reason, PositionUtils.IsPositionLiquidatableInfo memory info) = PositionUtils.isPositionLiquidatable(\n params.contracts.dataStore,\n params.contracts.referralStorage,\n params.position,\n params.market,\n cache.prices,\n true, // shouldValidateMinCollateralUsd\n true // forLiquidation\n );\n\n if (!isLiquidatable) {\n revert Errors.PositionShouldNotBeLiquidated(\n reason,\n info.remainingCollateralUsd,\n info.minCollateralUsd,\n info.minCollateralUsdForLeverage\n );\n }\n }\n\n cache.initialCollateralAmount = params.position.collateralAmount();\n (\n PositionUtils.DecreasePositionCollateralValues memory values,\n PositionPricingUtils.PositionFees memory fees\n ) = DecreasePositionCollateralUtils.processCollateral(\n params,\n cache\n );\n\n cache.nextPositionSizeInUsd = params.position.sizeInUsd() - params.order.sizeDeltaUsd();\n cache.nextPositionBorrowingFactor = MarketUtils.getCumulativeBorrowingFactor(params.contracts.dataStore, params.market.marketToken, params.position.isLong());\n\n PositionUtils.updateTotalBorrowing(\n params,\n cache.nextPositionSizeInUsd,\n cache.nextPositionBorrowingFactor\n );\n\n params.position.setSizeInUsd(cache.nextPositionSizeInUsd);\n params.position.setSizeInTokens(params.position.sizeInTokens() - values.sizeDeltaInTokens);\n params.position.setCollateralAmount(values.remainingCollateralAmount);\n params.position.setPendingImpactAmount(params.position.pendingImpactAmount() - values.proportionalPendingImpactAmount);\n params.position.setDecreasedAtTime(Chain.currentTimestamp());\n\n PositionUtils.incrementClaimableFundingAmount(params, fees);\n\n // subtract values.proportionalPendingImpactAmount from the total to remove it\n MarketUtils.applyDeltaToTotalPendingImpactAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n -values.proportionalPendingImpactAmount\n );\n\n if (params.position.sizeInUsd() == 0 || params.position.sizeInTokens() == 0) {\n // withdraw all collateral if the position will be closed\n values.output.outputAmount += params.position.collateralAmount();\n\n params.position.setSizeInUsd(0);\n params.position.setSizeInTokens(0);\n params.position.setCollateralAmount(0);\n\n PositionStoreUtils.remove(params.contracts.dataStore, params.positionKey, params.order.account());\n } else {\n params.position.setBorrowingFactor(cache.nextPositionBorrowingFactor);\n\n params.position.setFundingFeeAmountPerSize(fees.funding.latestFundingFeeAmountPerSize);\n params.position.setLongTokenClaimableFundingAmountPerSize(fees.funding.latestLongTokenClaimableFundingAmountPerSize);\n params.position.setShortTokenClaimableFundingAmountPerSize(fees.funding.latestShortTokenClaimableFundingAmountPerSize);\n\n PositionStoreUtils.set(params.contracts.dataStore, params.positionKey, params.position);\n }\n\n MarketUtils.applyDeltaToCollateralSum(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.position.market(),\n params.position.collateralToken(),\n params.position.isLong(),\n -(cache.initialCollateralAmount - params.position.collateralAmount()).toInt256()\n );\n\n PositionUtils.updateOpenInterest(\n params,\n -params.order.sizeDeltaUsd().toInt256(),\n -values.sizeDeltaInTokens.toInt256()\n );\n\n // affiliate rewards are still distributed even if the order is a liquidation order\n // this is expected as a partial liquidation is considered the same as an automatic\n // closing of a position\n PositionUtils.handleReferral(params, fees);\n\n // validatePosition should be called after open interest and all other market variables\n // have been updated\n if (params.position.sizeInUsd() != 0 || params.position.sizeInTokens() != 0) {\n // validate position which validates liquidation state is only called\n // if the remaining position size is not zero\n // due to this, a user can still manually close their position if\n // it is in a partially liquidatable state\n // this should not cause any issues as a liquidation is the same\n // as automatically closing a position\n // the only difference is that if the position has insufficient / negative\n // collateral a liquidation transaction should still complete\n // while a manual close transaction should revert\n PositionUtils.validatePosition(\n params.contracts.dataStore,\n params.contracts.referralStorage,\n params.position,\n params.market,\n cache.prices,\n false, // shouldValidateMinPositionSize\n false // shouldValidateMinCollateralUsd\n );\n }\n\n PositionEventUtils.emitPositionFeesCollected(\n params.contracts.eventEmitter,\n params.orderKey,\n params.positionKey,\n params.market.marketToken,\n params.position.collateralToken(),\n params.order.sizeDeltaUsd(),\n false,\n fees\n );\n\n PositionEventUtils.emitPositionDecrease(\n params.contracts.eventEmitter,\n params.orderKey,\n params.positionKey,\n params.position,\n params.order.sizeDeltaUsd(),\n cache.initialCollateralAmount - params.position.collateralAmount(),\n params.order.orderType(),\n values,\n cache.prices.indexTokenPrice,\n cache.collateralTokenPrice\n );\n\n values = DecreasePositionSwapUtils.swapWithdrawnCollateralToPnlToken(params, values);\n\n return DecreasePositionResult(\n values.output.outputToken,\n values.output.outputAmount,\n values.output.secondaryOutputToken,\n values.output.secondaryOutputAmount,\n params.order.sizeDeltaUsd(),\n params.order.initialCollateralDeltaAmount()\n );\n }\n}\n" + }, + "contracts/position/IncreasePositionUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"../pricing/PositionPricingUtils.sol\";\nimport \"../fee/FeeUtils.sol\";\n\nimport \"./Position.sol\";\nimport \"./PositionStoreUtils.sol\";\nimport \"./PositionUtils.sol\";\nimport \"./PositionEventUtils.sol\";\n\n// @title IncreasePositionUtils\n// @dev Library for functions to help with increasing a position\nlibrary IncreasePositionUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n\n using Position for Position.Props;\n using Order for Order.Props;\n using Price for Price.Props;\n\n // @dev IncreasePositionCache struct used in increasePosition to\n // avoid stack too deep errors\n // @param collateralDeltaAmount the change in collateral amount\n // @param executionPrice the execution price\n // @param collateralTokenPrice the price of the collateral token\n // @param priceImpactUsd the price impact in USD\n // @param priceImpactAmount the price impact of the position increase in tokens\n // @param sizeDeltaInTokens the change in position size in tokens\n // @param nextPositionSizeInUsd the new position size in USD\n // @param nextPositionBorrowingFactor the new position borrowing factor\n struct IncreasePositionCache {\n int256 collateralDeltaAmount;\n uint256 executionPrice;\n Price.Props collateralTokenPrice;\n int256 priceImpactUsd;\n int256 priceImpactAmount;\n bool balanceWasImproved;\n uint256 baseSizeDeltaInTokens;\n uint256 nextPositionSizeInUsd;\n uint256 nextPositionBorrowingFactor;\n }\n\n // @dev increase a position\n // The increasePosition function is used to increase the size of a position\n // in a market. This involves updating the position's collateral amount,\n // calculating the price impact of the size increase, and updating the position's\n // size and borrowing factor. This function also applies fees to the position\n // and updates the market's liquidity pool based on the new position size.\n // @param params PositionUtils.UpdatePositionParams\n function increasePosition(\n PositionUtils.UpdatePositionParams memory params,\n uint256 collateralIncrementAmount\n ) external {\n // get the market prices for the given position\n MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(\n params.contracts.oracle,\n params.market\n );\n\n // create a new cache for holding intermediate results\n IncreasePositionCache memory cache;\n\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\n params.position.collateralToken(),\n params.market,\n prices\n );\n\n if (params.position.sizeInUsd() == 0) {\n params.position.setFundingFeeAmountPerSize(\n MarketUtils.getFundingFeeAmountPerSize(\n params.contracts.dataStore,\n params.market.marketToken,\n params.position.collateralToken(),\n params.position.isLong()\n )\n );\n\n params.position.setLongTokenClaimableFundingAmountPerSize(\n MarketUtils.getClaimableFundingAmountPerSize(\n params.contracts.dataStore,\n params.market.marketToken,\n params.market.longToken,\n params.position.isLong()\n )\n );\n\n params.position.setShortTokenClaimableFundingAmountPerSize(\n MarketUtils.getClaimableFundingAmountPerSize(\n params.contracts.dataStore,\n params.market.marketToken,\n params.market.shortToken,\n params.position.isLong()\n )\n );\n }\n\n (\n cache.priceImpactUsd,\n cache.priceImpactAmount,\n cache.baseSizeDeltaInTokens,\n cache.executionPrice,\n cache.balanceWasImproved\n ) = PositionUtils.getExecutionPriceForIncrease(params, prices);\n\n // process the collateral for the given position and order\n PositionPricingUtils.PositionFees memory fees;\n (cache.collateralDeltaAmount, fees) = processCollateral(\n params,\n cache.collateralTokenPrice,\n collateralIncrementAmount.toInt256(),\n cache.balanceWasImproved\n );\n\n // check if there is sufficient collateral for the position\n if (\n cache.collateralDeltaAmount < 0 &&\n params.position.collateralAmount() < SafeCast.toUint256(-cache.collateralDeltaAmount)\n ) {\n revert Errors.InsufficientCollateralAmount(params.position.collateralAmount(), cache.collateralDeltaAmount);\n }\n params.position.setCollateralAmount(Calc.sumReturnUint256(params.position.collateralAmount(), cache.collateralDeltaAmount));\n\n // Instead of applying the delta to the pool, store it using the positionKey\n // No need to flip the priceImpactAmount sign since it isn't applied to the pool, it's just stored\n params.position.setPendingImpactAmount(params.position.pendingImpactAmount() + cache.priceImpactAmount);\n MarketUtils.applyDeltaToTotalPendingImpactAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n cache.priceImpactAmount\n );\n\n cache.nextPositionSizeInUsd = params.position.sizeInUsd() + params.order.sizeDeltaUsd();\n cache.nextPositionBorrowingFactor = MarketUtils.getCumulativeBorrowingFactor(\n params.contracts.dataStore,\n params.market.marketToken,\n params.position.isLong()\n );\n\n PositionUtils.updateTotalBorrowing(\n params,\n cache.nextPositionSizeInUsd,\n cache.nextPositionBorrowingFactor\n );\n\n PositionUtils.incrementClaimableFundingAmount(params, fees);\n\n params.position.setSizeInUsd(cache.nextPositionSizeInUsd);\n params.position.setSizeInTokens(params.position.sizeInTokens() + cache.baseSizeDeltaInTokens);\n\n params.position.setFundingFeeAmountPerSize(fees.funding.latestFundingFeeAmountPerSize);\n params.position.setLongTokenClaimableFundingAmountPerSize(fees.funding.latestLongTokenClaimableFundingAmountPerSize);\n params.position.setShortTokenClaimableFundingAmountPerSize(fees.funding.latestShortTokenClaimableFundingAmountPerSize);\n\n params.position.setBorrowingFactor(cache.nextPositionBorrowingFactor);\n params.position.setIncreasedAtTime(Chain.currentTimestamp());\n\n PositionStoreUtils.set(params.contracts.dataStore, params.positionKey, params.position);\n\n PositionUtils.updateOpenInterest(\n params,\n params.order.sizeDeltaUsd().toInt256(),\n cache.baseSizeDeltaInTokens.toInt256()\n );\n\n if (params.order.sizeDeltaUsd() > 0) {\n // reserves are only validated if the sizeDeltaUsd is more than zero\n // this helps to ensure that deposits of collateral into positions\n // should still succeed even if pool tokens are fully reserved\n MarketUtils.validateReserve(\n params.contracts.dataStore,\n params.market,\n prices,\n params.order.isLong()\n );\n\n MarketUtils.validateOpenInterestReserve(\n params.contracts.dataStore,\n params.market,\n prices,\n params.order.isLong()\n );\n\n PositionUtils.WillPositionCollateralBeSufficientValues memory positionValues = PositionUtils.WillPositionCollateralBeSufficientValues(\n params.position.sizeInUsd(), // positionSizeInUsd\n params.position.collateralAmount(), // positionCollateralAmount\n 0, // realizedPnlUsd\n 0 // openInterestDelta\n );\n\n (bool willBeSufficient, int256 remainingCollateralUsd) = PositionUtils.willPositionCollateralBeSufficient(\n params.contracts.dataStore,\n params.market,\n prices,\n params.position.collateralToken(),\n params.position.isLong(),\n positionValues\n );\n\n if (!willBeSufficient) {\n revert Errors.InsufficientCollateralUsd(remainingCollateralUsd);\n }\n }\n\n PositionUtils.handleReferral(params, fees);\n\n // validatePosition should be called after open interest and all other market variables\n // have been updated\n PositionUtils.validatePosition(\n params.contracts.dataStore,\n params.contracts.referralStorage,\n params.position,\n params.market,\n prices,\n true, // shouldValidateMinPositionSize\n true // shouldValidateMinCollateralUsd\n );\n\n PositionEventUtils.emitPositionFeesCollected(\n params.contracts.eventEmitter,\n params.orderKey,\n params.positionKey,\n params.market.marketToken,\n params.position.collateralToken(),\n params.order.sizeDeltaUsd(),\n true,\n fees\n );\n\n PositionEventUtils.PositionIncreaseParams memory eventParams;\n eventParams.eventEmitter = params.contracts.eventEmitter;\n eventParams.orderKey = params.orderKey;\n eventParams.positionKey = params.positionKey;\n eventParams.position = params.position;\n eventParams.indexTokenPrice = prices.indexTokenPrice;\n eventParams.executionPrice = cache.executionPrice;\n eventParams.collateralTokenPrice = cache.collateralTokenPrice;\n eventParams.sizeDeltaUsd = params.order.sizeDeltaUsd();\n eventParams.sizeDeltaInTokens = cache.baseSizeDeltaInTokens; // event key remains unchanged as it's used for e.g. analytics\n eventParams.collateralDeltaAmount = cache.collateralDeltaAmount;\n eventParams.priceImpactUsd = cache.priceImpactUsd;\n eventParams.priceImpactAmount = cache.priceImpactAmount;\n eventParams.orderType = params.order.orderType();\n\n PositionEventUtils.emitPositionIncrease(eventParams);\n }\n\n // @dev handle the collateral changes of the position\n // @param params PositionUtils.UpdatePositionParams\n // @param prices the prices of the tokens in the market\n // @param position the position to process collateral for\n // @param collateralDeltaAmount the change in the position's collateral\n function processCollateral(\n PositionUtils.UpdatePositionParams memory params,\n Price.Props memory collateralTokenPrice,\n int256 collateralDeltaAmount,\n bool balanceWasImproved\n ) internal returns (int256, PositionPricingUtils.PositionFees memory) {\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\n params.contracts.dataStore, // dataStore\n params.contracts.referralStorage, // referralStorage\n params.position, // position\n collateralTokenPrice, // collateralTokenPrice\n balanceWasImproved, // balanceWasImproved\n params.market.longToken, // longToken\n params.market.shortToken, // shortToken\n params.order.sizeDeltaUsd(), // sizeDeltaUsd\n params.order.uiFeeReceiver(), // uiFeeReceiver\n false // isLiquidation\n );\n\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\n\n FeeUtils.incrementClaimableFeeAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n params.position.collateralToken(),\n fees.feeReceiverAmount,\n Keys.POSITION_FEE_TYPE\n );\n\n FeeUtils.incrementClaimableUiFeeAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.order.uiFeeReceiver(),\n params.market.marketToken,\n params.position.collateralToken(),\n fees.ui.uiFeeAmount,\n Keys.UI_POSITION_FEE_TYPE\n );\n\n collateralDeltaAmount -= fees.totalCostAmount.toInt256();\n\n MarketUtils.applyDeltaToCollateralSum(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.order.market(),\n params.position.collateralToken(),\n params.order.isLong(),\n collateralDeltaAmount\n );\n\n MarketUtils.applyDeltaToPoolAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n params.position.collateralToken(),\n fees.feeAmountForPool.toInt256()\n );\n\n return (collateralDeltaAmount, fees);\n }\n}\n" + }, + "contracts/position/Position.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title Position\n// @dev Stuct for positions\n//\n// borrowing fees for position require only a borrowingFactor to track\n// an example on how this works is if the global cumulativeBorrowingFactor is 10020%\n// a position would be opened with borrowingFactor as 10020%\n// after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would\n// owe 5% of the position size as borrowing fees\n// the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs\n// when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's\n// collateral and transferred into the LP pool\n//\n// the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees\n// based on the fiat value of the position sizes\n//\n// for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position\n// claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would\n// only owe 0.05 longToken ($200)\n// this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts\n// to be deducted and to be paid out need to be tracked instead\n//\n// for funding fees, there are four values to consider:\n// 1. long positions with market.longToken as collateral\n// 2. long positions with market.shortToken as collateral\n// 3. short positions with market.longToken as collateral\n// 4. short positions with market.shortToken as collateral\nlibrary Position {\n // @dev there is a limit on the number of fields a struct can have when being passed\n // or returned as a memory variable which can cause \"Stack too deep\" errors\n // use sub-structs to avoid this issue\n // @param addresses address values\n // @param numbers number values\n // @param flags boolean values\n struct Props {\n Addresses addresses;\n Numbers numbers;\n Flags flags;\n }\n\n // @param account the position's account\n // @param market the position's market\n // @param collateralToken the position's collateralToken\n struct Addresses {\n address account;\n address market;\n address collateralToken;\n }\n\n // @param sizeInUsd the position's size in USD\n // @param sizeInTokens the position's size in tokens\n // @param collateralAmount the amount of collateralToken for collateral\n // @param pendingImpactAmount the amount of pending impact for the position\n // @param borrowingFactor the position's borrowing factor\n // @param fundingFeeAmountPerSize the position's funding fee per size\n // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\n // for the market.longToken\n // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size\n // for the market.shortToken\n // @param increasedAtTime the time at which this position was increased\n // @param decreasedAtTime the time at which this position was decreased\n struct Numbers {\n uint256 sizeInUsd;\n uint256 sizeInTokens;\n uint256 collateralAmount;\n int256 pendingImpactAmount;\n uint256 borrowingFactor;\n uint256 fundingFeeAmountPerSize;\n uint256 longTokenClaimableFundingAmountPerSize;\n uint256 shortTokenClaimableFundingAmountPerSize;\n uint256 increasedAtTime;\n uint256 decreasedAtTime;\n }\n\n // @param isLong whether the position is a long or short\n struct Flags {\n bool isLong;\n }\n\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n function market(Props memory props) internal pure returns (address) {\n return props.addresses.market;\n }\n\n function setMarket(Props memory props, address value) internal pure {\n props.addresses.market = value;\n }\n\n function collateralToken(Props memory props) internal pure returns (address) {\n return props.addresses.collateralToken;\n }\n\n function setCollateralToken(Props memory props, address value) internal pure {\n props.addresses.collateralToken = value;\n }\n\n function sizeInUsd(Props memory props) internal pure returns (uint256) {\n return props.numbers.sizeInUsd;\n }\n\n function setSizeInUsd(Props memory props, uint256 value) internal pure {\n props.numbers.sizeInUsd = value;\n }\n\n function sizeInTokens(Props memory props) internal pure returns (uint256) {\n return props.numbers.sizeInTokens;\n }\n\n function setSizeInTokens(Props memory props, uint256 value) internal pure {\n props.numbers.sizeInTokens = value;\n }\n\n function collateralAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.collateralAmount;\n }\n\n function setCollateralAmount(Props memory props, uint256 value) internal pure {\n props.numbers.collateralAmount = value;\n }\n\n function pendingImpactAmount(Props memory props) internal pure returns (int256) {\n return props.numbers.pendingImpactAmount;\n }\n\n function setPendingImpactAmount(Props memory props, int256 value) internal pure {\n props.numbers.pendingImpactAmount = value;\n }\n\n function borrowingFactor(Props memory props) internal pure returns (uint256) {\n return props.numbers.borrowingFactor;\n }\n\n function setBorrowingFactor(Props memory props, uint256 value) internal pure {\n props.numbers.borrowingFactor = value;\n }\n\n function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {\n return props.numbers.fundingFeeAmountPerSize;\n }\n\n function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {\n props.numbers.fundingFeeAmountPerSize = value;\n }\n\n function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\n return props.numbers.longTokenClaimableFundingAmountPerSize;\n }\n\n function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\n props.numbers.longTokenClaimableFundingAmountPerSize = value;\n }\n\n function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {\n return props.numbers.shortTokenClaimableFundingAmountPerSize;\n }\n\n function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {\n props.numbers.shortTokenClaimableFundingAmountPerSize = value;\n }\n\n function increasedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.increasedAtTime;\n }\n\n function setIncreasedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.increasedAtTime = value;\n }\n\n function decreasedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.decreasedAtTime;\n }\n\n function setDecreasedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.decreasedAtTime = value;\n }\n\n function isLong(Props memory props) internal pure returns (bool) {\n return props.flags.isLong;\n }\n\n function setIsLong(Props memory props, bool value) internal pure {\n props.flags.isLong = value;\n }\n\n // @dev get the key for a position\n // @param account the position's account\n // @param market the position's market\n // @param collateralToken the position's collateralToken\n // @param isLong whether the position is long or short\n // @return the position key\n function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {\n bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));\n\n return _key;\n }\n}\n" + }, + "contracts/position/PositionEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nimport \"./Position.sol\";\nimport \"./PositionUtils.sol\";\nimport \"../pricing/PositionPricingUtils.sol\";\n\nlibrary PositionEventUtils {\n using Position for Position.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n struct PositionIncreaseParams {\n EventEmitter eventEmitter;\n bytes32 orderKey;\n bytes32 positionKey;\n Position.Props position;\n Price.Props indexTokenPrice;\n Price.Props collateralTokenPrice;\n uint256 executionPrice;\n uint256 sizeDeltaUsd;\n uint256 sizeDeltaInTokens;\n int256 collateralDeltaAmount;\n int256 priceImpactUsd;\n int256 priceImpactAmount;\n Order.OrderType orderType;\n }\n\n function emitPositionIncrease(PositionIncreaseParams memory params) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"account\", params.position.account());\n eventData.addressItems.setItem(1, \"market\", params.position.market());\n eventData.addressItems.setItem(2, \"collateralToken\", params.position.collateralToken());\n\n eventData.uintItems.initItems(16);\n eventData.uintItems.setItem(0, \"sizeInUsd\", params.position.sizeInUsd());\n eventData.uintItems.setItem(1, \"sizeInTokens\", params.position.sizeInTokens());\n eventData.uintItems.setItem(2, \"collateralAmount\", params.position.collateralAmount());\n eventData.uintItems.setItem(3, \"borrowingFactor\", params.position.borrowingFactor());\n eventData.uintItems.setItem(4, \"fundingFeeAmountPerSize\", params.position.fundingFeeAmountPerSize());\n eventData.uintItems.setItem(5, \"longTokenClaimableFundingAmountPerSize\", params.position.longTokenClaimableFundingAmountPerSize());\n eventData.uintItems.setItem(6, \"shortTokenClaimableFundingAmountPerSize\", params.position.shortTokenClaimableFundingAmountPerSize());\n eventData.uintItems.setItem(7, \"executionPrice\", params.executionPrice);\n eventData.uintItems.setItem(8, \"indexTokenPrice.max\", params.indexTokenPrice.max);\n eventData.uintItems.setItem(9, \"indexTokenPrice.min\", params.indexTokenPrice.min);\n eventData.uintItems.setItem(10, \"collateralTokenPrice.max\", params.collateralTokenPrice.max);\n eventData.uintItems.setItem(11, \"collateralTokenPrice.min\", params.collateralTokenPrice.min);\n eventData.uintItems.setItem(12, \"sizeDeltaUsd\", params.sizeDeltaUsd);\n eventData.uintItems.setItem(13, \"sizeDeltaInTokens\", params.sizeDeltaInTokens);\n eventData.uintItems.setItem(14, \"orderType\", uint256(params.orderType));\n eventData.uintItems.setItem(15, \"increasedAtTime\", uint256(params.position.increasedAtTime()));\n\n eventData.intItems.initItems(3);\n eventData.intItems.setItem(0, \"collateralDeltaAmount\", params.collateralDeltaAmount);\n eventData.intItems.setItem(1, \"pendingPriceImpactUsd\", params.priceImpactUsd);\n eventData.intItems.setItem(2, \"pendingPriceImpactAmount\", params.priceImpactAmount);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", params.position.isLong());\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"orderKey\", params.orderKey);\n eventData.bytes32Items.setItem(1, \"positionKey\", params.positionKey);\n\n params.eventEmitter.emitEventLog1(\n \"PositionIncrease\",\n Cast.toBytes32(params.position.account()),\n eventData\n );\n }\n\n function emitPositionDecrease(\n EventEmitter eventEmitter,\n bytes32 orderKey,\n bytes32 positionKey,\n Position.Props memory position,\n uint256 sizeDeltaUsd,\n uint256 collateralDeltaAmount,\n Order.OrderType orderType,\n PositionUtils.DecreasePositionCollateralValues memory values,\n Price.Props memory indexTokenPrice,\n Price.Props memory collateralTokenPrice\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"account\", position.account());\n eventData.addressItems.setItem(1, \"market\", position.market());\n eventData.addressItems.setItem(2, \"collateralToken\", position.collateralToken());\n\n eventData.uintItems.initItems(18);\n eventData.uintItems.setItem(0, \"sizeInUsd\", position.sizeInUsd());\n eventData.uintItems.setItem(1, \"sizeInTokens\", position.sizeInTokens());\n eventData.uintItems.setItem(2, \"collateralAmount\", position.collateralAmount());\n eventData.uintItems.setItem(3, \"borrowingFactor\", position.borrowingFactor());\n eventData.uintItems.setItem(4, \"fundingFeeAmountPerSize\", position.fundingFeeAmountPerSize());\n eventData.uintItems.setItem(5, \"longTokenClaimableFundingAmountPerSize\", position.longTokenClaimableFundingAmountPerSize());\n eventData.uintItems.setItem(6, \"shortTokenClaimableFundingAmountPerSize\", position.shortTokenClaimableFundingAmountPerSize());\n eventData.uintItems.setItem(7, \"executionPrice\", values.executionPrice);\n eventData.uintItems.setItem(8, \"indexTokenPrice.max\", indexTokenPrice.max);\n eventData.uintItems.setItem(9, \"indexTokenPrice.min\", indexTokenPrice.min);\n eventData.uintItems.setItem(10, \"collateralTokenPrice.max\", collateralTokenPrice.max);\n eventData.uintItems.setItem(11, \"collateralTokenPrice.min\", collateralTokenPrice.min);\n eventData.uintItems.setItem(12, \"sizeDeltaUsd\", sizeDeltaUsd);\n eventData.uintItems.setItem(13, \"sizeDeltaInTokens\", values.sizeDeltaInTokens);\n eventData.uintItems.setItem(14, \"collateralDeltaAmount\", collateralDeltaAmount);\n eventData.uintItems.setItem(15, \"values.priceImpactDiffUsd\", values.priceImpactDiffUsd);\n eventData.uintItems.setItem(16, \"orderType\", uint256(orderType));\n eventData.uintItems.setItem(17, \"decreasedAtTime\", position.decreasedAtTime());\n\n eventData.intItems.initItems(5);\n eventData.intItems.setItem(0, \"priceImpactUsd\", values.priceImpactUsd);\n eventData.intItems.setItem(1, \"basePnlUsd\", values.basePnlUsd);\n eventData.intItems.setItem(2, \"uncappedBasePnlUsd\", values.uncappedBasePnlUsd);\n eventData.intItems.setItem(3, \"proportionalPendingImpactUsd\", values.proportionalPendingImpactUsd);\n eventData.intItems.setItem(4, \"totalImpactUsd\", values.totalImpactUsd);\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isLong\", position.isLong());\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"orderKey\", orderKey);\n eventData.bytes32Items.setItem(1, \"positionKey\", positionKey);\n\n eventEmitter.emitEventLog1(\n \"PositionDecrease\",\n Cast.toBytes32(position.account()),\n eventData\n );\n }\n\n function emitInsolventClose(\n EventEmitter eventEmitter,\n bytes32 orderKey,\n uint256 positionCollateralAmount,\n int256 basePnlUsd,\n uint256 remainingCostUsd,\n string memory step\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"orderKey\", orderKey);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"positionCollateralAmount\", positionCollateralAmount);\n eventData.uintItems.setItem(1, \"remainingCostUsd\", remainingCostUsd);\n\n eventData.intItems.initItems(1);\n eventData.intItems.setItem(0, \"basePnlUsd\", basePnlUsd);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"step\", step);\n\n eventEmitter.emitEventLog(\n \"InsolventClose\",\n eventData\n );\n }\n\n function emitInsufficientFundingFeePayment(\n EventEmitter eventEmitter,\n address market,\n address token,\n uint256 expectedAmount,\n uint256 amountPaidInCollateralToken,\n uint256 amountPaidInSecondaryOutputToken\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"expectedAmount\", expectedAmount);\n eventData.uintItems.setItem(1, \"amountPaidInCollateralToken\", amountPaidInCollateralToken);\n eventData.uintItems.setItem(2, \"amountPaidInSecondaryOutputToken\", amountPaidInSecondaryOutputToken);\n\n eventEmitter.emitEventLog1(\n \"InsufficientFundingFeePayment\",\n Cast.toBytes32(market),\n eventData\n );\n }\n\n function emitPositionFeesCollected(\n EventEmitter eventEmitter,\n bytes32 orderKey,\n bytes32 positionKey,\n address market,\n address collateralToken,\n uint256 tradeSizeUsd,\n bool isIncrease,\n PositionPricingUtils.PositionFees memory fees\n ) external {\n _emitPositionFees(\n eventEmitter,\n orderKey,\n positionKey,\n market,\n collateralToken,\n tradeSizeUsd,\n isIncrease,\n fees,\n \"PositionFeesCollected\"\n );\n }\n\n function emitPositionFeesInfo(\n EventEmitter eventEmitter,\n bytes32 orderKey,\n bytes32 positionKey,\n address market,\n address collateralToken,\n uint256 tradeSizeUsd,\n bool isIncrease,\n PositionPricingUtils.PositionFees memory fees\n ) external {\n _emitPositionFees(\n eventEmitter,\n orderKey,\n positionKey,\n market,\n collateralToken,\n tradeSizeUsd,\n isIncrease,\n fees,\n \"PositionFeesInfo\"\n );\n }\n\n function _emitPositionFees(\n EventEmitter eventEmitter,\n bytes32 orderKey,\n bytes32 positionKey,\n address market,\n address collateralToken,\n uint256 tradeSizeUsd,\n bool isIncrease,\n PositionPricingUtils.PositionFees memory fees,\n string memory eventName\n ) internal {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(3);\n eventData.bytes32Items.setItem(0, \"orderKey\", orderKey);\n eventData.bytes32Items.setItem(1, \"positionKey\", positionKey);\n eventData.bytes32Items.setItem(2, \"referralCode\", fees.referral.referralCode);\n\n eventData.addressItems.initItems(5);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"collateralToken\", collateralToken);\n eventData.addressItems.setItem(2, \"affiliate\", fees.referral.affiliate);\n eventData.addressItems.setItem(3, \"trader\", fees.referral.trader);\n eventData.addressItems.setItem(4, \"uiFeeReceiver\", fees.ui.uiFeeReceiver);\n\n // in case the position was insolvent, the fundingFeeAmount and feeAmountForPool\n // values may not be accurate\n\n uint256 uintItemsCount = 23;\n uint256 dynamicItemIndex = uintItemsCount - 1;\n if (fees.referral.totalRebateFactor > 0) {\n uintItemsCount += 6;\n }\n if (fees.liquidation.liquidationFeeAmount > 0) {\n uintItemsCount += 3;\n }\n if (fees.pro.traderDiscountFactor > 0) {\n uintItemsCount += 2;\n }\n\n eventData.uintItems.initItems(uintItemsCount);\n eventData.uintItems.setItem(0, \"collateralTokenPrice.min\", fees.collateralTokenPrice.min);\n eventData.uintItems.setItem(1, \"collateralTokenPrice.max\", fees.collateralTokenPrice.max);\n eventData.uintItems.setItem(2, \"tradeSizeUsd\", tradeSizeUsd);\n eventData.uintItems.setItem(3, \"fundingFeeAmount\", fees.funding.fundingFeeAmount);\n eventData.uintItems.setItem(4, \"claimableLongTokenAmount\", fees.funding.claimableLongTokenAmount);\n eventData.uintItems.setItem(5, \"claimableShortTokenAmount\", fees.funding.claimableShortTokenAmount);\n eventData.uintItems.setItem(6, \"latestFundingFeeAmountPerSize\", fees.funding.latestFundingFeeAmountPerSize);\n eventData.uintItems.setItem(7, \"latestLongTokenClaimableFundingAmountPerSize\", fees.funding.latestLongTokenClaimableFundingAmountPerSize);\n eventData.uintItems.setItem(8, \"latestShortTokenClaimableFundingAmountPerSize\", fees.funding.latestShortTokenClaimableFundingAmountPerSize);\n eventData.uintItems.setItem(9, \"borrowingFeeUsd\", fees.borrowing.borrowingFeeUsd);\n eventData.uintItems.setItem(10, \"borrowingFeeAmount\", fees.borrowing.borrowingFeeAmount);\n eventData.uintItems.setItem(11, \"borrowingFeeReceiverFactor\", fees.borrowing.borrowingFeeReceiverFactor);\n eventData.uintItems.setItem(12, \"borrowingFeeAmountForFeeReceiver\", fees.borrowing.borrowingFeeAmountForFeeReceiver);\n eventData.uintItems.setItem(13, \"positionFeeFactor\", fees.positionFeeFactor);\n eventData.uintItems.setItem(14, \"protocolFeeAmount\", fees.protocolFeeAmount);\n eventData.uintItems.setItem(15, \"positionFeeReceiverFactor\", fees.positionFeeReceiverFactor);\n eventData.uintItems.setItem(16, \"feeReceiverAmount\", fees.feeReceiverAmount);\n eventData.uintItems.setItem(17, \"feeAmountForPool\", fees.feeAmountForPool);\n eventData.uintItems.setItem(18, \"positionFeeAmountForPool\", fees.positionFeeAmountForPool);\n eventData.uintItems.setItem(19, \"positionFeeAmount\", fees.positionFeeAmount);\n eventData.uintItems.setItem(20, \"totalCostAmount\", fees.totalCostAmount);\n eventData.uintItems.setItem(21, \"uiFeeReceiverFactor\", fees.ui.uiFeeReceiverFactor);\n eventData.uintItems.setItem(22, \"uiFeeAmount\", fees.ui.uiFeeAmount);\n\n // ++dynamicItemIndex is pre-increment, first the value is incremented, then updated value is returned\n // i.e. if dynamicItemIndex is 22, then ++dynamicItemIndex returns 23\n if (fees.referral.totalRebateFactor > 0) {\n eventData.uintItems.setItem(++dynamicItemIndex, \"referral.totalRebateFactor\", fees.referral.totalRebateFactor);\n eventData.uintItems.setItem(++dynamicItemIndex, \"referral.adjustedAffiliateRewardFactor\", fees.referral.adjustedAffiliateRewardFactor);\n eventData.uintItems.setItem(++dynamicItemIndex, \"referral.traderDiscountFactor\", fees.referral.traderDiscountFactor);\n eventData.uintItems.setItem(++dynamicItemIndex, \"referral.totalRebateAmount\", fees.referral.totalRebateAmount);\n eventData.uintItems.setItem(++dynamicItemIndex, \"referral.traderDiscountAmount\", fees.referral.traderDiscountAmount);\n eventData.uintItems.setItem(++dynamicItemIndex, \"referral.affiliateRewardAmount\", fees.referral.affiliateRewardAmount);\n }\n if (fees.pro.traderDiscountFactor > 0) {\n eventData.uintItems.setItem(++dynamicItemIndex, \"pro.traderDiscountFactor\", fees.pro.traderDiscountFactor);\n eventData.uintItems.setItem(++dynamicItemIndex, \"pro.traderDiscountAmount\", fees.pro.traderDiscountAmount);\n }\n if (fees.liquidation.liquidationFeeAmount > 0) {\n eventData.uintItems.setItem(++dynamicItemIndex, \"liquidationFeeAmount\", fees.liquidation.liquidationFeeAmount);\n eventData.uintItems.setItem(++dynamicItemIndex, \"liquidationFeeReceiverFactor\", fees.liquidation.liquidationFeeReceiverFactor);\n eventData.uintItems.setItem(++dynamicItemIndex, \"liquidationFeeAmountForFeeReceiver\", fees.liquidation.liquidationFeeAmountForFeeReceiver);\n }\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"isIncrease\", isIncrease);\n\n eventEmitter.emitEventLog1(\n eventName,\n Cast.toBytes32(market),\n eventData\n );\n }\n}\n" + }, + "contracts/position/PositionStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Position.sol\";\n\n/**\n * @title PositionStoreUtils\n * @dev Library for position storage functions\n */\nlibrary PositionStoreUtils {\n using Position for Position.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant MARKET = keccak256(abi.encode(\"MARKET\"));\n bytes32 public constant COLLATERAL_TOKEN = keccak256(abi.encode(\"COLLATERAL_TOKEN\"));\n\n bytes32 public constant SIZE_IN_USD = keccak256(abi.encode(\"SIZE_IN_USD\"));\n bytes32 public constant SIZE_IN_TOKENS = keccak256(abi.encode(\"SIZE_IN_TOKENS\"));\n bytes32 public constant COLLATERAL_AMOUNT = keccak256(abi.encode(\"COLLATERAL_AMOUNT\"));\n bytes32 public constant PENDING_IMPACT_AMOUNT = keccak256(abi.encode(\"PENDING_IMPACT_AMOUNT\"));\n bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode(\"BORROWING_FACTOR\"));\n bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode(\"FUNDING_FEE_AMOUNT_PER_SIZE\"));\n bytes32 public constant LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\"LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\"));\n bytes32 public constant SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode(\"SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE\"));\n bytes32 public constant INCREASED_AT_TIME = keccak256(abi.encode(\"INCREASED_AT_TIME\"));\n bytes32 public constant DECREASED_AT_TIME = keccak256(abi.encode(\"DECREASED_AT_TIME\"));\n\n bytes32 public constant IS_LONG = keccak256(abi.encode(\"IS_LONG\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (Position.Props memory) {\n Position.Props memory position;\n if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) {\n return position;\n }\n\n position.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n position.setMarket(dataStore.getAddress(\n keccak256(abi.encode(key, MARKET))\n ));\n\n position.setCollateralToken(dataStore.getAddress(\n keccak256(abi.encode(key, COLLATERAL_TOKEN))\n ));\n\n position.setSizeInUsd(dataStore.getUint(\n keccak256(abi.encode(key, SIZE_IN_USD))\n ));\n\n position.setSizeInTokens(dataStore.getUint(\n keccak256(abi.encode(key, SIZE_IN_TOKENS))\n ));\n\n position.setCollateralAmount(dataStore.getUint(\n keccak256(abi.encode(key, COLLATERAL_AMOUNT))\n ));\n\n position.setPendingImpactAmount(dataStore.getInt(\n keccak256(abi.encode(key, PENDING_IMPACT_AMOUNT))\n ));\n\n position.setBorrowingFactor(dataStore.getUint(\n keccak256(abi.encode(key, BORROWING_FACTOR))\n ));\n\n position.setFundingFeeAmountPerSize(dataStore.getUint(\n keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE))\n ));\n\n position.setLongTokenClaimableFundingAmountPerSize(dataStore.getUint(\n keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))\n ));\n\n position.setShortTokenClaimableFundingAmountPerSize(dataStore.getUint(\n keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))\n ));\n\n position.setIncreasedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, INCREASED_AT_TIME))\n ));\n\n position.setDecreasedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, DECREASED_AT_TIME))\n ));\n\n position.setIsLong(dataStore.getBool(\n keccak256(abi.encode(key, IS_LONG))\n ));\n\n return position;\n }\n\n function set(DataStore dataStore, bytes32 key, Position.Props memory position) external {\n dataStore.addBytes32(\n Keys.POSITION_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountPositionListKey(position.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n position.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET)),\n position.market()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, COLLATERAL_TOKEN)),\n position.collateralToken()\n );\n\n dataStore.setInt(\n keccak256(abi.encode(key, PENDING_IMPACT_AMOUNT)),\n position.pendingImpactAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SIZE_IN_USD)),\n position.sizeInUsd()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SIZE_IN_TOKENS)),\n position.sizeInTokens()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, COLLATERAL_AMOUNT)),\n position.collateralAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, BORROWING_FACTOR)),\n position.borrowingFactor()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE)),\n position.fundingFeeAmountPerSize()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)),\n position.longTokenClaimableFundingAmountPerSize()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)),\n position.shortTokenClaimableFundingAmountPerSize()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, INCREASED_AT_TIME)),\n position.increasedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, DECREASED_AT_TIME)),\n position.decreasedAtTime()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, IS_LONG)),\n position.isLong()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) {\n revert Errors.PositionNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.POSITION_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountPositionListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, COLLATERAL_TOKEN))\n );\n\n dataStore.removeInt(\n keccak256(abi.encode(key, PENDING_IMPACT_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SIZE_IN_USD))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SIZE_IN_TOKENS))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, COLLATERAL_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, BORROWING_FACTOR))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, INCREASED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, DECREASED_AT_TIME))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, IS_LONG))\n );\n }\n\n function getPositionCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.POSITION_LIST);\n }\n\n function getPositionKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end);\n }\n\n function getAccountPositionCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountPositionListKey(account));\n }\n\n function getAccountPositionKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountPositionListKey(account), start, end);\n }\n}\n" + }, + "contracts/position/PositionUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport \"../utils/Precision.sol\";\n\nimport \"./Position.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\n\nimport \"../pricing/PositionPricingUtils.sol\";\nimport \"../order/BaseOrderUtils.sol\";\n\n// @title PositionUtils\n// @dev Library for position functions\nlibrary PositionUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n using Price for Price.Props;\n using Position for Position.Props;\n using Order for Order.Props;\n\n // @dev UpdatePositionParams struct used in increasePosition and decreasePosition\n // to avoid stack too deep errors\n //\n // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts\n // @param market the values of the trading market\n // @param order the decrease position order\n // @param orderKey the key of the order\n // @param position the order's position\n // @param positionKey the key of the order's position\n struct UpdatePositionParams {\n BaseOrderUtils.ExecuteOrderParamsContracts contracts;\n Market.Props market;\n Order.Props order;\n bytes32 orderKey;\n Position.Props position;\n bytes32 positionKey;\n Order.SecondaryOrderType secondaryOrderType;\n }\n\n // @param dataStore DataStore\n // @param eventEmitter EventEmitter\n // @param oracle Oracle\n // @param referralStorage IReferralStorage\n struct UpdatePositionParamsContracts {\n DataStore dataStore;\n EventEmitter eventEmitter;\n IOracle oracle;\n ISwapHandler swapHandler;\n IReferralStorage referralStorage;\n }\n\n struct WillPositionCollateralBeSufficientValues {\n uint256 positionSizeInUsd;\n uint256 positionCollateralAmount;\n int256 realizedPnlUsd;\n int256 openInterestDelta;\n }\n\n struct DecreasePositionCollateralValuesOutput {\n address outputToken;\n uint256 outputAmount;\n address secondaryOutputToken;\n uint256 secondaryOutputAmount;\n }\n\n // @dev ProcessCollateralValues struct used to contain the values in processCollateral\n // @param executionPrice the order execution price\n // @param remainingCollateralAmount the remaining collateral amount of the position\n // @param positionPnlUsd the pnl of the position in USD\n // @param sizeDeltaInTokens the change in position size in tokens\n // @param priceImpactAmount the price impact in tokens\n // @param priceImpactDiffUsd the price impact difference in USD\n // @param pendingCollateralDeduction the pending collateral deduction\n // @param output DecreasePositionCollateralValuesOutput\n struct DecreasePositionCollateralValues {\n uint256 executionPrice;\n uint256 remainingCollateralAmount;\n int256 basePnlUsd;\n int256 uncappedBasePnlUsd;\n uint256 sizeDeltaInTokens;\n int256 priceImpactUsd;\n int256 proportionalPendingImpactAmount;\n int256 proportionalPendingImpactUsd;\n uint256 priceImpactDiffUsd;\n int256 totalImpactUsd;\n DecreasePositionCollateralValuesOutput output;\n }\n\n // @dev DecreasePositionCache struct used in decreasePosition to\n // avoid stack too deep errors\n // @param prices the prices of the tokens in the market\n // @param pnlToken the token that the pnl for the user is in, for long positions\n // this is the market.longToken, for short positions this is the market.shortToken\n // @param pnlTokenPrice the price of the pnlToken\n // @param initialCollateralAmount the initial collateral amount\n // @param nextPositionSizeInUsd the new position size in USD\n // @param nextPositionBorrowingFactor the new position borrowing factor\n struct DecreasePositionCache {\n MarketUtils.MarketPrices prices;\n int256 estimatedPositionPnlUsd;\n int256 estimatedRealizedPnlUsd;\n int256 estimatedRemainingPnlUsd;\n address pnlToken;\n Price.Props pnlTokenPrice;\n Price.Props collateralTokenPrice;\n uint256 initialCollateralAmount;\n uint256 nextPositionSizeInUsd;\n uint256 nextPositionBorrowingFactor;\n int256 minCollateralUsd;\n }\n\n\n struct GetPositionPnlUsdCache {\n int256 positionValue;\n int256 totalPositionPnl;\n int256 uncappedTotalPositionPnl;\n address pnlToken;\n uint256 poolTokenAmount;\n uint256 poolTokenPrice;\n uint256 poolTokenUsd;\n int256 poolPnl;\n int256 cappedPoolPnl;\n uint256 sizeDeltaInTokens;\n int256 positionPnlUsd;\n int256 uncappedPositionPnlUsd;\n }\n\n struct IsPositionLiquidatableInfo {\n int256 remainingCollateralUsd;\n int256 minCollateralUsd;\n int256 minCollateralUsdForLeverage;\n }\n\n struct IsPositionLiquidatableCache {\n int256 positionPnlUsd;\n uint256 minCollateralFactor;\n Price.Props collateralTokenPrice;\n uint256 collateralUsd;\n int256 usdDeltaForPriceImpact;\n int256 priceImpactUsd;\n bool balanceWasImproved;\n }\n\n struct GetExecutionPriceForIncreaseCache {\n int256 priceImpactUsd;\n int256 priceImpactAmount;\n uint256 baseSizeDeltaInTokens;\n bool balanceWasImproved;\n uint256 executionPrice;\n }\n\n struct GetExecutionPriceForDecreaseCache {\n int256 priceImpactUsd;\n bool balanceWasImproved;\n uint256 executionPrice;\n }\n\n // @dev get the position pnl in USD\n //\n // for long positions, pnl is calculated as:\n // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd\n // if position.sizeInTokens is larger for long positions, the position will have\n // larger profits and smaller losses for the same changes in token price\n //\n // for short positions, pnl is calculated as:\n // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)\n // if position.sizeInTokens is smaller for long positions, the position will have\n // larger profits and smaller losses for the same changes in token price\n //\n // @param position the position values\n // @param sizeDeltaUsd the change in position size\n // @param indexTokenPrice the price of the index token\n //\n // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)\n function getPositionPnlUsd(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n Position.Props memory position,\n uint256 sizeDeltaUsd\n ) public view returns (int256, int256, uint256) {\n GetPositionPnlUsdCache memory cache;\n\n uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);\n\n // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens\n cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();\n cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;\n cache.uncappedTotalPositionPnl = cache.totalPositionPnl;\n\n if (cache.totalPositionPnl > 0) {\n cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;\n cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);\n cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;\n cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;\n cache.poolPnl = MarketUtils.getPnl(\n dataStore,\n market,\n prices.indexTokenPrice,\n position.isLong(),\n true\n );\n\n cache.cappedPoolPnl = MarketUtils.getCappedPnl(\n dataStore,\n market.marketToken,\n position.isLong(),\n cache.poolPnl,\n cache.poolTokenUsd,\n Keys.MAX_PNL_FACTOR_FOR_TRADERS\n );\n\n if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {\n cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());\n }\n }\n\n if (position.sizeInUsd() == sizeDeltaUsd) {\n cache.sizeDeltaInTokens = position.sizeInTokens();\n } else {\n if (position.isLong()) {\n cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());\n } else {\n cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();\n }\n }\n\n cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\n cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());\n\n return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);\n }\n\n // @dev validate that a position is not empty\n // @param position the position values\n function validateNonEmptyPosition(Position.Props memory position) internal pure {\n if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {\n revert Errors.EmptyPosition();\n }\n }\n\n // @dev check if a position is valid\n // @param dataStore DataStore\n // @param referralStorage IReferralStorage\n // @param position the position values\n // @param market the market values\n // @param prices the prices of the tokens in the market\n // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated\n // validation is skipped for decrease position to prevent reverts in case the order size\n // is just slightly smaller than the position size\n // in decrease position, the remaining collateral is estimated at the start, and the order\n // size is updated to match the position size if the remaining collateral will be less than\n // the min collateral usd\n // since this is an estimate, there may be edge cases where there is a small remaining position size\n // and small amount of collateral remaining\n // validation is skipped for this case as it is preferred for the order to be executed\n // since the small amount of collateral remaining only impacts the potential payment of liquidation\n // keepers\n function validatePosition(\n DataStore dataStore,\n IReferralStorage referralStorage,\n Position.Props memory position,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n bool shouldValidateMinPositionSize,\n bool shouldValidateMinCollateralUsd\n ) public view {\n if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {\n revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());\n }\n\n MarketUtils.validateEnabledMarket(dataStore, market.marketToken);\n MarketUtils.validateMarketCollateralToken(market, position.collateralToken());\n\n if (shouldValidateMinPositionSize) {\n uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);\n if (position.sizeInUsd() < minPositionSizeUsd) {\n revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);\n }\n }\n\n (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(\n dataStore,\n referralStorage,\n position,\n market,\n prices,\n shouldValidateMinCollateralUsd,\n false // forLiquidation\n );\n\n if (isLiquidatable) {\n revert Errors.LiquidatablePosition(\n reason,\n info.remainingCollateralUsd,\n info.minCollateralUsd,\n info.minCollateralUsdForLeverage\n );\n }\n }\n\n function isPositionLiquidatable(\n DataStore dataStore,\n IReferralStorage referralStorage,\n Position.Props memory position,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n bool shouldValidateMinCollateralUsd,\n bool forLiquidation\n ) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {\n IsPositionLiquidatableCache memory cache;\n IsPositionLiquidatableInfo memory info;\n\n (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(\n dataStore,\n market,\n prices,\n position,\n position.sizeInUsd()\n );\n\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(\n position.collateralToken(),\n market,\n prices\n );\n\n cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;\n\n // calculate the usdDeltaForPriceImpact for fully closing the position\n cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();\n\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\n PositionPricingUtils.GetPriceImpactUsdParams(\n dataStore,\n market,\n cache.usdDeltaForPriceImpact,\n position.isLong()\n )\n );\n\n // cap positive priceImpactUsd based on the max positive position impact factor\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\n dataStore,\n market.marketToken,\n cache.priceImpactUsd,\n position.sizeInUsd()\n );\n\n cache.priceImpactUsd += position.pendingImpactAmount() > 0\n ? position.pendingImpactAmount() * prices.indexTokenPrice.min.toInt256()\n : position.pendingImpactAmount() * prices.indexTokenPrice.max.toInt256();\n\n // even if there is a large positive price impact, positions that would be liquidated\n // if the positive price impact is reduced should not be allowed to be created\n // as they would be easily liquidated if the price impact changes\n // cap the priceImpactUsd to zero to prevent these positions from being created\n if (cache.priceImpactUsd >= 0) {\n cache.priceImpactUsd = 0;\n } else {\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(\n dataStore,\n market.marketToken\n );\n\n // if there is a large build up of open interest and a sudden large price movement\n // it may result in a large imbalance between longs and shorts\n // this could result in very large price impact temporarily\n // cap the max negative price impact to prevent cascading liquidations\n int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();\n if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {\n cache.priceImpactUsd = maxNegativePriceImpactUsd;\n }\n }\n\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(\n dataStore, // dataStore\n referralStorage, // referralStorage\n position, // position\n cache.collateralTokenPrice, //collateralTokenPrice\n cache.balanceWasImproved, // balanceWasImproved\n market.longToken, // longToken\n market.shortToken, // shortToken\n position.sizeInUsd(), // sizeDeltaUsd\n address(0), // uiFeeReceiver\n\n // should not account for liquidation fees to determine if position should be liquidated\n false // isLiquidation\n );\n\n PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\n\n // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD\n // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated\n // using collateralTokenPrice.min\n uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;\n\n // the position's pnl is counted as collateral for the liquidation check\n // as a position in profit should not be liquidated if the pnl is sufficient\n // to cover the position's fees\n info.remainingCollateralUsd =\n cache.collateralUsd.toInt256()\n + cache.positionPnlUsd\n + cache.priceImpactUsd\n - collateralCostUsd.toInt256();\n\n if (forLiquidation) {\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactorForLiquidation(dataStore, market.marketToken);\n } else {\n cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\n }\n\n // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)\n // this validation includes the position fee to be paid when closing the position\n // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position\n info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();\n\n if (shouldValidateMinCollateralUsd) {\n info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();\n if (info.remainingCollateralUsd < info.minCollateralUsd) {\n return (true, \"min collateral\", info);\n }\n }\n\n if (info.remainingCollateralUsd <= 0) {\n return (true, \"< 0\", info);\n }\n\n if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {\n return (true, \"min collateral for leverage\", info);\n }\n\n return (false, \"\", info);\n }\n\n // fees and price impact are not included for the willPositionCollateralBeSufficient validation\n // this is because this validation is meant to guard against a specific scenario of price impact\n // gaming\n //\n // price impact could be gamed by opening high leverage positions, if the price impact\n // that should be charged is higher than the amount of collateral in the position\n // then a user could pay less price impact than what is required, and there is a risk that\n // price manipulation could be profitable if the price impact cost is less than it should be\n //\n // this check should be sufficient even without factoring in fees as fees should have a minimal impact\n // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could\n // lead to a user paying less price impact than they should, however gaming of this form should be difficult\n // since the funding and borrowing fees would still add up for the user's cost\n //\n // another possibility would be if a user opens a large amount of both long and short positions, and\n // funding fees are paid from one side to the other, but since most of the open interest is owned by the\n // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant\n // since some time would be required for the funding fees to accumulate\n //\n // fees and price impact are validated in the validatePosition check\n function willPositionCollateralBeSufficient(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n address collateralToken,\n bool isLong,\n WillPositionCollateralBeSufficientValues memory values\n ) public view returns (bool, int256) {\n Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(\n collateralToken,\n market,\n prices\n );\n\n int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();\n\n // deduct realized pnl if it is negative since this would be paid from\n // the position's collateral\n if (values.realizedPnlUsd < 0) {\n remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;\n }\n\n if (remainingCollateralUsd < 0) {\n return (false, remainingCollateralUsd);\n }\n\n // the min collateral factor will increase as the open interest for a market increases\n // this may lead to previously created limit increase orders not being executable\n //\n // the position's pnl is not factored into the remainingCollateralUsd value, since\n // factoring in a positive pnl may allow the user to manipulate price and bypass this check\n // it may be useful to factor in a negative pnl for this check, this can be added if required\n uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(\n dataStore,\n market,\n values.openInterestDelta,\n isLong\n );\n\n uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);\n // use the minCollateralFactor for the market if it is larger\n if (minCollateralFactorForMarket > minCollateralFactor) {\n minCollateralFactor = minCollateralFactorForMarket;\n }\n\n int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();\n bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;\n\n return (willBeSufficient, remainingCollateralUsd);\n }\n\n function updateFundingAndBorrowingState(\n DataStore dataStore,\n EventEmitter eventEmitter,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices\n ) external {\n // update the funding amount per size for the market\n MarketUtils.updateFundingState(\n dataStore,\n eventEmitter,\n market,\n prices\n );\n\n // update the cumulative borrowing factor for longs\n MarketUtils.updateCumulativeBorrowingFactor(\n dataStore,\n eventEmitter,\n market,\n prices,\n true // isLong\n );\n\n // update the cumulative borrowing factor for shorts\n MarketUtils.updateCumulativeBorrowingFactor(\n dataStore,\n eventEmitter,\n market,\n prices,\n false // isLong\n );\n }\n\n function updateTotalBorrowing(\n PositionUtils.UpdatePositionParams memory params,\n uint256 nextPositionSizeInUsd,\n uint256 nextPositionBorrowingFactor\n ) internal {\n MarketUtils.updateTotalBorrowing(\n params.contracts.dataStore, // dataStore\n params.market.marketToken, // market\n params.position.isLong(), // isLong\n params.position.sizeInUsd(), // prevPositionSizeInUsd\n params.position.borrowingFactor(), // prevPositionBorrowingFactor\n nextPositionSizeInUsd, // nextPositionSizeInUsd\n nextPositionBorrowingFactor // nextPositionBorrowingFactor\n );\n }\n\n // the order.receiver is meant to allow the output of an order to be\n // received by an address that is different from the position.account\n // address\n // for funding fees, the funds are still credited to the owner\n // of the position indicated by order.account\n function incrementClaimableFundingAmount(\n PositionUtils.UpdatePositionParams memory params,\n PositionPricingUtils.PositionFees memory fees\n ) internal {\n // if the position has negative funding fees, distribute it to allow it to be claimable\n if (fees.funding.claimableLongTokenAmount > 0) {\n MarketUtils.incrementClaimableFundingAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n params.market.longToken,\n params.order.account(),\n fees.funding.claimableLongTokenAmount\n );\n }\n\n if (fees.funding.claimableShortTokenAmount > 0) {\n MarketUtils.incrementClaimableFundingAmount(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market.marketToken,\n params.market.shortToken,\n params.order.account(),\n fees.funding.claimableShortTokenAmount\n );\n }\n }\n\n function updateOpenInterest(\n PositionUtils.UpdatePositionParams memory params,\n int256 sizeDeltaUsd,\n int256 sizeDeltaInTokens\n ) internal {\n if (sizeDeltaUsd != 0) {\n MarketUtils.applyDeltaToOpenInterest(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.market,\n params.position.collateralToken(),\n params.position.isLong(),\n sizeDeltaUsd\n );\n\n MarketUtils.applyDeltaToOpenInterestInTokens(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.position.market(),\n params.position.collateralToken(),\n params.position.isLong(),\n sizeDeltaInTokens\n );\n }\n }\n\n function handleReferral(\n PositionUtils.UpdatePositionParams memory params,\n PositionPricingUtils.PositionFees memory fees\n ) internal {\n ReferralUtils.incrementAffiliateReward(\n params.contracts.dataStore,\n params.contracts.eventEmitter,\n params.position.market(),\n params.position.collateralToken(),\n fees.referral.affiliate,\n fees.referral.affiliateRewardAmount\n );\n }\n\n // returns priceImpactUsd, priceImpactAmount, baseSizeDeltaInTokens, executionPrice, balanceWasImproved\n function getExecutionPriceForIncrease(\n UpdatePositionParams memory params,\n MarketUtils.MarketPrices memory prices\n ) external view returns (int256, int256, uint256, uint256, bool) {\n // note that the executionPrice is not validated against the order.acceptablePrice value\n // if the sizeDeltaUsd is zero\n // for limit orders the order.triggerPrice should still have been validated\n if (params.order.sizeDeltaUsd() == 0) {\n // increase order:\n // - long: use the larger price\n // - short: use the smaller price\n return (0, 0, 0, prices.indexTokenPrice.pickPrice(params.position.isLong()), false);\n }\n\n GetExecutionPriceForIncreaseCache memory cache;\n\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\n PositionPricingUtils.GetPriceImpactUsdParams(\n params.contracts.dataStore,\n params.market,\n params.order.sizeDeltaUsd().toInt256(),\n params.order.isLong()\n )\n );\n\n // cap positive priceImpactUsd based on the max positive position impact factor\n // note that the positive priceImpactUsd is not capped by the position impact pool here\n // this is to prevent cases where for new markets, user A opens a position with negative\n // price impact and user B does not have any incentive to open a position to balance the pool\n // because the price impact pool is empty until user A closes\n // the positive price impact will still be capped during position decrease when the positive\n // price impact is actually paid out\n //\n // we do not call capPositiveImpactUsdByPositionImpactPool for increase as we are\n // uncertain when the impact pool state would be when the position is actually\n // closed and the impact is to be realized\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\n params.contracts.dataStore,\n params.market.marketToken,\n cache.priceImpactUsd,\n params.order.sizeDeltaUsd()\n );\n\n // for long positions\n //\n // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount\n // the priceImpactAmount should be minimized\n //\n // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount\n // the priceImpactAmount should be maximized\n\n // for short positions\n //\n // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount\n // the priceImpactAmount should be minimized\n //\n // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount\n // the priceImpactAmount should be maximized\n\n if (cache.priceImpactUsd > 0) {\n // use indexTokenPrice.max and round down to minimize the priceImpactAmount\n cache.priceImpactAmount = cache.priceImpactUsd / prices.indexTokenPrice.max.toInt256();\n } else {\n // use indexTokenPrice.min and round up to maximize the priceImpactAmount\n cache.priceImpactAmount = Calc.roundUpMagnitudeDivision(cache.priceImpactUsd, prices.indexTokenPrice.min);\n }\n\n if (params.position.isLong()) {\n // round the number of tokens for long positions down\n cache.baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / prices.indexTokenPrice.max;\n } else {\n // round the number of tokens for short positions up\n cache.baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), prices.indexTokenPrice.min);\n }\n\n int256 sizeDeltaInTokens;\n if (params.position.isLong()) {\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() + cache.priceImpactAmount;\n } else {\n sizeDeltaInTokens = cache.baseSizeDeltaInTokens.toInt256() - cache.priceImpactAmount;\n }\n\n if (sizeDeltaInTokens < 0) {\n revert Errors.PriceImpactLargerThanOrderSize(cache.priceImpactUsd, params.order.sizeDeltaUsd());\n }\n\n // using increase of long positions as an example\n // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000\n // priceImpactAmount = -1000 / 2000 = -0.5\n // baseSizeDeltaInTokens = 5000 / 2000 = 2.5\n // sizeDeltaInTokens = 2.5 - 0.5 = 2\n // executionPrice = 5000 / 2 = $2500\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(\n params.order.sizeDeltaUsd(),\n sizeDeltaInTokens.toUint256(),\n params.order.acceptablePrice(),\n params.position.isLong()\n );\n\n return (cache.priceImpactUsd, cache.priceImpactAmount, cache.baseSizeDeltaInTokens, cache.executionPrice, cache.balanceWasImproved);\n }\n\n // returns priceImpactUsd, executionPrice, balanceWasImproved\n function getExecutionPriceForDecrease(\n UpdatePositionParams memory params,\n Price.Props memory indexTokenPrice\n ) external view returns (int256, uint256, bool) {\n uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();\n\n // note that the executionPrice is not validated against the order.acceptablePrice value\n // if the sizeDeltaUsd is zero\n // for limit orders the order.triggerPrice should still have been validated\n if (sizeDeltaUsd == 0) {\n // decrease order:\n // - long: use the smaller price\n // - short: use the larger price\n return (0, indexTokenPrice.pickPrice(!params.position.isLong()), false);\n }\n\n GetExecutionPriceForDecreaseCache memory cache;\n\n (cache.priceImpactUsd, cache.balanceWasImproved) = PositionPricingUtils.getPriceImpactUsd(\n PositionPricingUtils.GetPriceImpactUsdParams(\n params.contracts.dataStore,\n params.market,\n -sizeDeltaUsd.toInt256(),\n params.order.isLong()\n )\n );\n\n // cap positive priceImpactUsd based on the max positive position impact factor\n cache.priceImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\n params.contracts.dataStore,\n params.market.marketToken,\n cache.priceImpactUsd,\n params.order.sizeDeltaUsd()\n );\n\n cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(\n indexTokenPrice,\n params.position.sizeInUsd(),\n params.position.sizeInTokens(),\n sizeDeltaUsd,\n cache.priceImpactUsd,\n params.order.acceptablePrice(),\n params.position.isLong()\n );\n\n return (cache.priceImpactUsd, cache.executionPrice, cache.balanceWasImproved);\n }\n}\n" + }, + "contracts/price/Price.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title Price\n// @dev Struct for prices\nlibrary Price {\n // @param min the min price\n // @param max the max price\n struct Props {\n uint256 min;\n uint256 max;\n }\n\n // @dev check if a price is empty\n // @param props Props\n // @return whether a price is empty\n function isEmpty(Props memory props) internal pure returns (bool) {\n return props.min == 0 || props.max == 0;\n }\n\n // @dev get the average of the min and max values\n // @param props Props\n // @return the average of the min and max values\n function midPrice(Props memory props) internal pure returns (uint256) {\n return (props.max + props.min) / 2;\n }\n\n // @dev pick either the min or max value\n // @param props Props\n // @param maximize whether to pick the min or max value\n // @return either the min or max value\n function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {\n return maximize ? props.max : props.min;\n }\n\n // @dev pick the min or max price depending on whether it is for a long or short position\n // and whether the pending pnl should be maximized or not\n // @param props Props\n // @param isLong whether it is for a long or short position\n // @param maximize whether the pnl should be maximized or not\n // @return the min or max price\n function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {\n // for long positions, pick the larger price to maximize pnl\n // for short positions, pick the smaller price to maximize pnl\n if (isLong) {\n return maximize ? props.max : props.min;\n }\n\n return maximize ? props.min : props.max;\n }\n}\n" + }, + "contracts/pricing/ISwapPricingUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface ISwapPricingUtils {\n enum SwapPricingType {\n Swap,\n Shift,\n AtomicWithdrawal,\n Deposit,\n Withdrawal,\n AtomicSwap\n }\n}\n" + }, + "contracts/pricing/PositionPricingUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\nimport \"../market/MarketUtils.sol\";\n\nimport \"../utils/Precision.sol\";\nimport \"../utils/Calc.sol\";\n\nimport \"./PricingUtils.sol\";\n\nimport \"../referral/IReferralStorage.sol\";\nimport \"../referral/ReferralUtils.sol\";\n\n// @title PositionPricingUtils\n// @dev Library for position pricing functions\nlibrary PositionPricingUtils {\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n using Position for Position.Props;\n using Price for Price.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n struct GetPositionFeesParams {\n DataStore dataStore;\n IReferralStorage referralStorage;\n Position.Props position;\n Price.Props collateralTokenPrice;\n bool balanceWasImproved;\n address longToken;\n address shortToken;\n uint256 sizeDeltaUsd;\n address uiFeeReceiver;\n bool isLiquidation;\n }\n\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack\n // too deep errors\n // @param dataStore DataStore\n // @param market the market to check\n // @param usdDelta the change in position size in USD\n // @param isLong whether the position is long or short\n struct GetPriceImpactUsdParams {\n DataStore dataStore;\n Market.Props market;\n int256 usdDelta;\n bool isLong;\n }\n\n // @dev OpenInterestParams struct to contain open interest values\n // @param longOpenInterest the amount of long open interest\n // @param shortOpenInterest the amount of short open interest\n // @param nextLongOpenInterest the updated amount of long open interest\n // @param nextShortOpenInterest the updated amount of short open interest\n struct OpenInterestParams {\n uint256 longOpenInterest;\n uint256 shortOpenInterest;\n uint256 nextLongOpenInterest;\n uint256 nextShortOpenInterest;\n }\n\n // @dev PositionFees struct to contain fee values\n // @param feeReceiverAmount the amount for the fee receiver\n // @param feeAmountForPool the amount of fees for the pool\n // @param positionFeeAmountForPool the position fee amount for the pool\n // @param positionFeeAmount the fee amount for increasing / decreasing the position\n // @param borrowingFeeAmount the borrowing fee amount\n // @param totalCostAmount the total cost amount in tokens\n struct PositionFees {\n PositionReferralFees referral;\n PositionProFees pro;\n PositionFundingFees funding;\n PositionBorrowingFees borrowing;\n PositionUiFees ui;\n PositionLiquidationFees liquidation;\n Price.Props collateralTokenPrice;\n uint256 positionFeeFactor;\n uint256 protocolFeeAmount;\n uint256 positionFeeReceiverFactor;\n uint256 feeReceiverAmount;\n uint256 feeAmountForPool;\n uint256 positionFeeAmountForPool;\n uint256 positionFeeAmount;\n uint256 totalCostAmountExcludingFunding;\n uint256 totalCostAmount;\n uint256 totalDiscountAmount;\n }\n\n struct PositionProFees {\n uint256 traderTier;\n uint256 traderDiscountFactor;\n uint256 traderDiscountAmount;\n }\n\n struct PositionLiquidationFees {\n uint256 liquidationFeeUsd;\n uint256 liquidationFeeAmount;\n uint256 liquidationFeeReceiverFactor;\n uint256 liquidationFeeAmountForFeeReceiver;\n }\n\n // @param affiliate the referral affiliate of the trader\n // @param traderDiscountAmount the discount amount for the trader\n // @param affiliateRewardAmount the affiliate reward amount\n struct PositionReferralFees {\n bytes32 referralCode;\n address affiliate;\n address trader;\n uint256 totalRebateFactor;\n uint256 affiliateRewardFactor;\n uint256 adjustedAffiliateRewardFactor;\n uint256 traderDiscountFactor;\n uint256 totalRebateAmount;\n uint256 traderDiscountAmount;\n uint256 affiliateRewardAmount;\n }\n\n struct PositionBorrowingFees {\n uint256 borrowingFeeUsd;\n uint256 borrowingFeeAmount;\n uint256 borrowingFeeReceiverFactor;\n uint256 borrowingFeeAmountForFeeReceiver;\n }\n\n // @param fundingFeeAmount the position's funding fee amount\n // @param claimableLongTokenAmount the negative funding fee in long token that is claimable\n // @param claimableShortTokenAmount the negative funding fee in short token that is claimable\n // @param latestLongTokenFundingAmountPerSize the latest long token funding\n // amount per size for the market\n // @param latestShortTokenFundingAmountPerSize the latest short token funding\n // amount per size for the market\n struct PositionFundingFees {\n uint256 fundingFeeAmount;\n uint256 claimableLongTokenAmount;\n uint256 claimableShortTokenAmount;\n uint256 latestFundingFeeAmountPerSize;\n uint256 latestLongTokenClaimableFundingAmountPerSize;\n uint256 latestShortTokenClaimableFundingAmountPerSize;\n }\n\n struct PositionUiFees {\n address uiFeeReceiver;\n uint256 uiFeeReceiverFactor;\n uint256 uiFeeAmount;\n }\n\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\n // @param params GetPriceImpactUsdParams and the balanceWasImproved boolean\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256, bool) {\n OpenInterestParams memory openInterestParams = getNextOpenInterest(params);\n\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);\n\n // the virtual price impact calculation is skipped if the price impact\n // is positive since the action is helping to balance the pool\n //\n // in case two virtual pools are unbalanced in a different direction\n // e.g. pool0 has more longs than shorts while pool1 has less longs\n // than shorts\n // not skipping the virtual price impact calculation would lead to\n // a negative price impact for any trade on either pools and would\n // disincentivise the balancing of pools\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\n\n (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);\n if (!hasVirtualInventory) { return (priceImpactUsd, balanceWasImproved); }\n\n OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);\n\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\n }\n\n // @dev get the price impact in USD for a position increase / decrease and whether the balance was improved\n // @param dataStore DataStore\n // @param market the trading market\n // @param openInterestParams OpenInterestParams and the balanceWasImproved boolean\n function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256, bool) {\n uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);\n uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);\n\n // check whether an improvement in balance comes from causing the balance to switch sides\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\n bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;\n uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));\n\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\n if (isSameSideRebalance) {\n uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, balanceWasImproved);\n\n return (\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\n initialDiffUsd,\n nextDiffUsd,\n impactFactor,\n impactExponentFactor\n ),\n balanceWasImproved\n );\n } else {\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);\n\n return (\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\n initialDiffUsd,\n nextDiffUsd,\n positiveImpactFactor,\n negativeImpactFactor,\n impactExponentFactor\n ),\n balanceWasImproved\n );\n }\n }\n\n // @dev get the next open interest values\n // @param params GetPriceImpactUsdParams\n // @return OpenInterestParams\n function getNextOpenInterest(\n GetPriceImpactUsdParams memory params\n ) internal view returns (OpenInterestParams memory) {\n uint256 longOpenInterest = MarketUtils.getOpenInterest(\n params.dataStore,\n params.market,\n true\n );\n\n uint256 shortOpenInterest = MarketUtils.getOpenInterest(\n params.dataStore,\n params.market,\n false\n );\n\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\n }\n\n function getNextOpenInterestForVirtualInventory(\n GetPriceImpactUsdParams memory params,\n int256 virtualInventory\n ) internal pure returns (OpenInterestParams memory) {\n uint256 longOpenInterest;\n uint256 shortOpenInterest;\n\n // if virtualInventory is more than zero it means that\n // tokens were virtually sold to the pool, so set shortOpenInterest\n // to the virtualInventory value\n // if virtualInventory is less than zero it means that\n // tokens were virtually bought from the pool, so set longOpenInterest\n // to the virtualInventory value\n if (virtualInventory > 0) {\n shortOpenInterest = virtualInventory.toUint256();\n } else {\n longOpenInterest = (-virtualInventory).toUint256();\n }\n\n // the virtual long and short open interest is adjusted by the usdDelta\n // to prevent an underflow in getNextOpenInterestParams\n // price impact depends on the change in USD balance, so offsetting both\n // values equally should not change the price impact calculation\n if (params.usdDelta < 0) {\n uint256 offset = (-params.usdDelta).toUint256();\n longOpenInterest += offset;\n shortOpenInterest += offset;\n }\n\n return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);\n }\n\n function getNextOpenInterestParams(\n GetPriceImpactUsdParams memory params,\n uint256 longOpenInterest,\n uint256 shortOpenInterest\n ) internal pure returns (OpenInterestParams memory) {\n uint256 nextLongOpenInterest = longOpenInterest;\n uint256 nextShortOpenInterest = shortOpenInterest;\n\n if (params.isLong) {\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {\n revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);\n }\n\n nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);\n } else {\n if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {\n revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);\n }\n\n nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);\n }\n\n OpenInterestParams memory openInterestParams = OpenInterestParams(\n longOpenInterest,\n shortOpenInterest,\n nextLongOpenInterest,\n nextShortOpenInterest\n );\n\n return openInterestParams;\n }\n\n // @dev get position fees\n // @param dataStore DataStore\n // @param referralStorage IReferralStorage\n // @param position the position values\n // @param collateralTokenPrice the price of the position's collateralToken\n // @param longToken the long token of the market\n // @param shortToken the short token of the market\n // @param sizeDeltaUsd the change in position size\n // @return PositionFees\n function getPositionFees(\n GetPositionFeesParams memory params\n ) internal view returns (PositionFees memory) {\n PositionFees memory fees = getPositionFeesAfterReferral(\n params.dataStore,\n params.referralStorage,\n params.collateralTokenPrice,\n params.balanceWasImproved,\n params.position.account(),\n params.position.market(),\n params.sizeDeltaUsd\n );\n\n uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);\n\n fees.borrowing = getBorrowingFees(\n params.dataStore,\n params.collateralTokenPrice,\n borrowingFeeUsd\n );\n\n if (params.isLiquidation) {\n fees.liquidation = getLiquidationFees(params.dataStore, params.position.market(), params.sizeDeltaUsd, params.collateralTokenPrice);\n }\n\n fees.feeAmountForPool =\n fees.positionFeeAmountForPool +\n fees.borrowing.borrowingFeeAmount -\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\n fees.liquidation.liquidationFeeAmount -\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\n\n fees.feeReceiverAmount +=\n fees.borrowing.borrowingFeeAmountForFeeReceiver +\n fees.liquidation.liquidationFeeAmountForFeeReceiver;\n\n fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\n params.dataStore,\n params.position.market(),\n params.position.collateralToken(),\n params.position.isLong()\n );\n\n fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\n params.dataStore,\n params.position.market(),\n params.longToken,\n params.position.isLong()\n );\n\n fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\n params.dataStore,\n params.position.market(),\n params.shortToken,\n params.position.isLong()\n );\n\n fees.funding = getFundingFees(\n fees.funding,\n params.position\n );\n\n fees.ui = getUiFees(\n params.dataStore,\n params.collateralTokenPrice,\n params.sizeDeltaUsd,\n params.uiFeeReceiver\n );\n\n fees.totalCostAmountExcludingFunding =\n fees.positionFeeAmount\n + fees.borrowing.borrowingFeeAmount\n + fees.liquidation.liquidationFeeAmount\n + fees.ui.uiFeeAmount\n - fees.totalDiscountAmount;\n\n fees.totalCostAmount =\n fees.totalCostAmountExcludingFunding\n + fees.funding.fundingFeeAmount;\n\n return fees;\n }\n\n function getBorrowingFees(\n DataStore dataStore,\n Price.Props memory collateralTokenPrice,\n uint256 borrowingFeeUsd\n ) internal view returns (PositionBorrowingFees memory) {\n PositionBorrowingFees memory borrowingFees;\n\n borrowingFees.borrowingFeeUsd = borrowingFeeUsd;\n borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;\n borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);\n borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);\n\n return borrowingFees;\n }\n\n function getFundingFees(\n PositionFundingFees memory fundingFees,\n Position.Props memory position\n ) internal pure returns (PositionFundingFees memory) {\n fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(\n fundingFees.latestFundingFeeAmountPerSize,\n position.fundingFeeAmountPerSize(),\n position.sizeInUsd(),\n true // roundUpMagnitude\n );\n\n fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(\n fundingFees.latestLongTokenClaimableFundingAmountPerSize,\n position.longTokenClaimableFundingAmountPerSize(),\n position.sizeInUsd(),\n false // roundUpMagnitude\n );\n\n fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(\n fundingFees.latestShortTokenClaimableFundingAmountPerSize,\n position.shortTokenClaimableFundingAmountPerSize(),\n position.sizeInUsd(),\n false // roundUpMagnitude\n );\n\n return fundingFees;\n }\n\n function getUiFees(\n DataStore dataStore,\n Price.Props memory collateralTokenPrice,\n uint256 sizeDeltaUsd,\n address uiFeeReceiver\n ) internal view returns (PositionUiFees memory) {\n PositionUiFees memory uiFees;\n\n if (uiFeeReceiver == address(0)) {\n return uiFees;\n }\n\n uiFees.uiFeeReceiver = uiFeeReceiver;\n uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\n uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;\n\n return uiFees;\n }\n\n // @dev get position fees after applying referral rebates / discounts\n // @param dataStore DataStore\n // @param referralStorage IReferralStorage\n // @param collateralTokenPrice the price of the position's collateralToken\n // @param the position's account\n // @param market the position's market\n // @param sizeDeltaUsd the change in position size\n // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)\n function getPositionFeesAfterReferral(\n DataStore dataStore,\n IReferralStorage referralStorage,\n Price.Props memory collateralTokenPrice,\n bool balanceWasImproved,\n address account,\n address market,\n uint256 sizeDeltaUsd\n ) internal view returns (PositionFees memory) {\n PositionFees memory fees;\n\n fees.collateralTokenPrice = collateralTokenPrice;\n\n fees.referral.trader = account;\n uint256 minAffiliateRewardFactor;\n (\n fees.referral.referralCode,\n fees.referral.affiliate,\n fees.referral.affiliateRewardFactor,\n fees.referral.traderDiscountFactor,\n minAffiliateRewardFactor\n ) = ReferralUtils.getReferralInfo(dataStore, referralStorage, account);\n\n // note that since it is possible to incur both positive and negative price impact values\n // and the negative price impact factor may be larger than the positive impact factor\n // it is possible for the balance to be improved overall but for the price impact to still be negative\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\n fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, balanceWasImproved));\n fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;\n\n // pro tiers are provided as a flexible option to allow for custom criteria based discounts,\n // the exact criteria and usage of this feature should be decided by the DAO\n fees.pro.traderTier = dataStore.getUint(Keys.proTraderTierKey(account));\n if (fees.pro.traderTier > 0) {\n fees.pro.traderDiscountFactor = dataStore.getUint(Keys.proDiscountFactorKey(fees.pro.traderTier));\n\n if (fees.pro.traderDiscountFactor > 0) {\n fees.pro.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.pro.traderDiscountFactor);\n }\n }\n\n // if pro discount is higher than referral discount then affiliate reward is capped at (total referral rebate - pro discount)\n // but can not be lower than configured min affiliate reward\n //\n // example 1:\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 5%\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 5%, 5%) = 15%\n // trader gets 10% discount, affiliate reward is capped at 15%, affiliate gets full 10% reward\n // protocol gets 80%\n //\n // example 2:\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 13%\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 13%, 5%) = 7%\n // trader gets 13% discount, affiliate reward is capped at 7%, affiliate gets capped 7% reward\n // protocol gets 80%\n //\n // example 3:\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 18%\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 18%, 5%) = 5%\n // trader gets 18% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\n // protocol gets 77%\n //\n // example 4:\n // referral code is 10% affiliate reward and 10% trader discount, pro discount is 25%\n // min affiliate reward 5%, total referral rebate is 20%, affiliate reward cap is max of (20% - 25%, 5%) = 5%\n // trader gets 25% discount, affiliate reward is capped at 5%, affiliate gets capped 5% reward\n // protocol gets 70%\n\n if (fees.referral.referralCode != bytes32(0)) {\n fees.referral.adjustedAffiliateRewardFactor = fees.referral.affiliateRewardFactor;\n fees.referral.totalRebateFactor = fees.referral.affiliateRewardFactor + fees.referral.traderDiscountFactor;\n // if pro discount is higher than referral discount then affiliate reward should be capped\n // at max of (min affiliate reward, total referral rebate - pro discount)\n if (fees.pro.traderDiscountFactor > fees.referral.traderDiscountFactor) {\n fees.referral.adjustedAffiliateRewardFactor = fees.pro.traderDiscountFactor > fees.referral.totalRebateFactor\n ? minAffiliateRewardFactor\n : fees.referral.totalRebateFactor - fees.pro.traderDiscountFactor;\n if (fees.referral.adjustedAffiliateRewardFactor < minAffiliateRewardFactor) {\n fees.referral.adjustedAffiliateRewardFactor = minAffiliateRewardFactor;\n }\n }\n\n fees.referral.affiliateRewardAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.adjustedAffiliateRewardFactor);\n fees.referral.traderDiscountAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.traderDiscountFactor);\n fees.referral.totalRebateAmount = fees.referral.affiliateRewardAmount + fees.referral.traderDiscountAmount;\n }\n\n fees.totalDiscountAmount = fees.pro.traderDiscountAmount > fees.referral.traderDiscountAmount\n ? fees.pro.traderDiscountAmount\n : fees.referral.traderDiscountAmount;\n fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.affiliateRewardAmount - fees.totalDiscountAmount;\n\n fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);\n fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);\n fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;\n\n return fees;\n }\n\n function getLiquidationFees(DataStore dataStore, address market, uint256 sizeInUsd, Price.Props memory collateralTokenPrice) internal view returns (PositionLiquidationFees memory) {\n PositionLiquidationFees memory liquidationFees;\n uint256 liquidationFeeFactor = dataStore.getUint(Keys.liquidationFeeFactorKey(market));\n if (liquidationFeeFactor == 0) {\n return liquidationFees;\n }\n\n liquidationFees.liquidationFeeUsd = Precision.applyFactor(sizeInUsd, liquidationFeeFactor);\n liquidationFees.liquidationFeeAmount = Calc.roundUpDivision(liquidationFees.liquidationFeeUsd, collateralTokenPrice.min);\n liquidationFees.liquidationFeeReceiverFactor = dataStore.getUint(Keys.LIQUIDATION_FEE_RECEIVER_FACTOR);\n liquidationFees.liquidationFeeAmountForFeeReceiver = Precision.applyFactor(liquidationFees.liquidationFeeAmount, liquidationFees.liquidationFeeReceiverFactor);\n return liquidationFees;\n }\n}\n" + }, + "contracts/pricing/PricingUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Calc.sol\";\nimport \"../utils/Precision.sol\";\n\n// @title PricingUtils\n// @dev Library for pricing functions\n//\n// Price impact is calculated as:\n//\n// ```\n// (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)\n// ```\n//\n// For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the\n// difference in the worth of the long tokens and short tokens.\n//\n// For example:\n//\n// - A pool has 10 long tokens, each long token is worth $5000\n// - The pool also has 50,000 short tokens, each short token is worth $1\n// - The `price impact exponent` is set to 2 and `price impact factor` is set\n// to `0.01 / 50,000`\n// - The pool is equally balanced with $50,000 of long tokens and $50,000 of\n// short tokens\n// - If a user deposits 10 long tokens, the pool would now have $100,000 of long\n// tokens and $50,000 of short tokens\n// - The change in imbalance would be from $0 to -$50,000\n// - There would be negative price impact charged on the user's deposit,\n// calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`\n// - If the user now withdraws 5 long tokens, the balance would change\n// from -$50,000 to -$25,000, a net change of +$25,000\n// - There would be a positive price impact rebated to the user in the form of\n// additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`\n//\n// For position actions (increase / decrease position), imbalance is calculated\n// as the difference in the long and short open interest.\n//\n// `price impact exponents` and `price impact factors` are configured per market\n// and can differ for spot and position actions.\n//\n// The purpose of the price impact is to help reduce the risk of price manipulation,\n// since the contracts use an oracle price which would be an average or median price\n// of multiple reference exchanges. Without a price impact, it may be profitable to\n// manipulate the prices on reference exchanges while executing orders on the contracts.\n//\n// This risk will also be present if the positive and negative price impact values\n// are similar, for that reason the positive price impact should be set to a low\n// value in times of volatility or irregular price movements.\nlibrary PricingUtils {\n // @dev get the price impact USD if there is no crossover in balance\n // a crossover in balance is for example if the long open interest is larger\n // than the short open interest, and a short position is opened such that the\n // short open interest becomes larger than the long open interest\n // @param initialDiffUsd the initial difference in USD\n // @param nextDiffUsd the next difference in USD\n // @param impactFactor the impact factor\n // @param impactExponentFactor the impact exponent factor\n function getPriceImpactUsdForSameSideRebalance(\n uint256 initialDiffUsd,\n uint256 nextDiffUsd,\n uint256 impactFactor,\n uint256 impactExponentFactor\n ) internal pure returns (int256) {\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\n\n uint256 deltaDiffUsd = Calc.diff(\n applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),\n applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)\n );\n\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, balanceWasImproved);\n\n return priceImpactUsd;\n }\n\n // @dev get the price impact USD if there is a crossover in balance\n // a crossover in balance is for example if the long open interest is larger\n // than the short open interest, and a short position is opened such that the\n // short open interest becomes larger than the long open interest\n // @param initialDiffUsd the initial difference in USD\n // @param nextDiffUsd the next difference in USD\n // @param impactFactor the impact factor\n // @param impactExponentFactor the impact exponent factor\n function getPriceImpactUsdForCrossoverRebalance(\n uint256 initialDiffUsd,\n uint256 nextDiffUsd,\n uint256 positiveImpactFactor,\n uint256 negativeImpactFactor,\n uint256 impactExponentFactor\n ) internal pure returns (int256) {\n uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);\n uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);\n uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);\n\n int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);\n\n return priceImpactUsd;\n }\n\n // @dev apply the impact factor calculation to a USD diff value\n // @param diffUsd the difference in USD\n // @param impactFactor the impact factor\n // @param impactExponentFactor the impact exponent factor\n function applyImpactFactor(\n uint256 diffUsd,\n uint256 impactFactor,\n uint256 impactExponentFactor\n ) internal pure returns (uint256) {\n uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);\n return Precision.applyFactor(exponentValue, impactFactor);\n }\n}\n" + }, + "contracts/pricing/SwapPricingUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\nimport \"../market/MarketUtils.sol\";\n\nimport \"../utils/Precision.sol\";\nimport \"../utils/Calc.sol\";\n\nimport \"./PricingUtils.sol\";\nimport \"./ISwapPricingUtils.sol\";\n\n// @title SwapPricingUtils\n// @dev Library for pricing functions\nlibrary SwapPricingUtils {\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to\n // avoid stack too deep errors\n // @param dataStore DataStore\n // @param market the market to check\n // @param tokenA the token to check balance for\n // @param tokenB the token to check balance for\n // @param priceForTokenA the price for tokenA\n // @param priceForTokenB the price for tokenB\n // @param usdDeltaForTokenA the USD change in amount of tokenA\n // @param usdDeltaForTokenB the USD change in amount of tokenB\n struct GetPriceImpactUsdParams {\n DataStore dataStore;\n Market.Props market;\n address tokenA;\n address tokenB;\n uint256 priceForTokenA;\n uint256 priceForTokenB;\n int256 usdDeltaForTokenA;\n int256 usdDeltaForTokenB;\n bool includeVirtualInventoryImpact;\n }\n\n struct EmitSwapInfoParams {\n bytes32 orderKey;\n address market;\n address receiver;\n address tokenIn;\n address tokenOut;\n uint256 tokenInPrice;\n uint256 tokenOutPrice;\n uint256 amountIn;\n uint256 amountInAfterFees;\n uint256 amountOut;\n int256 priceImpactUsd;\n int256 priceImpactAmount;\n int256 tokenInPriceImpactAmount;\n }\n\n // @dev PoolParams struct to contain pool values\n // @param poolUsdForTokenA the USD value of tokenA in the pool\n // @param poolUsdForTokenB the USD value of tokenB in the pool\n // @param nextPoolUsdForTokenA the next USD value of tokenA in the pool\n // @param nextPoolUsdForTokenB the next USD value of tokenB in the pool\n struct PoolParams {\n uint256 poolUsdForTokenA;\n uint256 poolUsdForTokenB;\n uint256 nextPoolUsdForTokenA;\n uint256 nextPoolUsdForTokenB;\n }\n\n // @dev SwapFees struct to contain swap fee values\n // @param feeReceiverAmount the fee amount for the fee receiver\n // @param feeAmountForPool the fee amount for the pool\n // @param amountAfterFees the output amount after fees\n struct SwapFees {\n uint256 feeReceiverAmount;\n uint256 feeAmountForPool;\n uint256 amountAfterFees;\n\n address uiFeeReceiver;\n uint256 uiFeeReceiverFactor;\n uint256 uiFeeAmount;\n }\n\n // @dev get the price impact in USD\n //\n // note that there will be some difference between the pool amounts used for\n // calculating the price impact and fees vs the actual pool amounts after the\n // swap is done, since the pool amounts will be increased / decreased by an amount\n // after factoring in the calculated price impact and fees\n //\n // since the calculations are based on the real-time prices values of the tokens\n // if a token price increases, the pool will incentivise swapping out more of that token\n // this is useful if prices are ranging, if prices are strongly directional, the pool may\n // be selling tokens as the token price increases\n //\n // @param params GetPriceImpactUsdParams\n //\n // @return the price impact in USD and the balanceWasImproved boolean\n function getPriceImpactUsd(GetPriceImpactUsdParams memory params) external view returns (int256, bool) {\n PoolParams memory poolParams = getNextPoolAmountsUsd(params);\n\n (int256 priceImpactUsd, bool balanceWasImproved) = _getPriceImpactUsd(params.dataStore, params.market, poolParams);\n\n // the virtual price impact calculation is skipped if the price impact\n // is positive since the action is helping to balance the pool\n //\n // in case two virtual pools are unbalanced in a different direction\n // e.g. pool0 has more WNT than USDC while pool1 has less WNT\n // than USDT\n // not skipping the virtual price impact calculation would lead to\n // a negative price impact for any trade on either pools and would\n // disincentivise the balancing of pools\n if (priceImpactUsd >= 0) { return (priceImpactUsd, balanceWasImproved); }\n\n if (!params.includeVirtualInventoryImpact) {\n return (priceImpactUsd, balanceWasImproved);\n }\n\n // note that the virtual pool for the long token / short token may be different across pools\n // e.g. ETH/USDC, ETH/USDT would have USDC and USDT as the short tokens\n // the short token amount is multiplied by the price of the token in the current pool, e.g. if the swap\n // is for the ETH/USDC pool, the combined USDC and USDT short token amounts is multiplied by the price of\n // USDC to calculate the price impact, this should be reasonable most of the time unless there is a\n // large depeg of one of the tokens, in which case it may be necessary to remove that market from being a virtual\n // market, removal of virtual markets may lead to incorrect virtual token accounting, the feature to correct for\n // this can be added if needed\n (bool hasVirtualInventory, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils.getVirtualInventoryForSwaps(\n params.dataStore,\n params.market.marketToken\n );\n\n if (!hasVirtualInventory) {\n return (priceImpactUsd, balanceWasImproved);\n }\n\n uint256 virtualPoolAmountForTokenA;\n uint256 virtualPoolAmountForTokenB;\n\n if (params.tokenA == params.market.longToken) {\n virtualPoolAmountForTokenA = virtualPoolAmountForLongToken;\n virtualPoolAmountForTokenB = virtualPoolAmountForShortToken;\n } else {\n virtualPoolAmountForTokenA = virtualPoolAmountForShortToken;\n virtualPoolAmountForTokenB = virtualPoolAmountForLongToken;\n }\n\n PoolParams memory poolParamsForVirtualInventory = getNextPoolAmountsParams(\n params,\n virtualPoolAmountForTokenA,\n virtualPoolAmountForTokenB\n );\n\n (int256 priceImpactUsdForVirtualInventory, bool balanceWasImprovedForVirtualInventory) = _getPriceImpactUsd(params.dataStore, params.market, poolParamsForVirtualInventory);\n\n return priceImpactUsdForVirtualInventory < priceImpactUsd ? (priceImpactUsdForVirtualInventory, balanceWasImprovedForVirtualInventory) : (priceImpactUsd, balanceWasImproved);\n }\n\n // @dev get the price impact in USD and whether the balance was improved\n // @param dataStore DataStore\n // @param market the trading market\n // @param poolParams PoolParams\n // @return the price impact in USD and the balanceWasImproved boolean\n function _getPriceImpactUsd(DataStore dataStore, Market.Props memory market, PoolParams memory poolParams) internal view returns (int256, bool) {\n uint256 initialDiffUsd = Calc.diff(poolParams.poolUsdForTokenA, poolParams.poolUsdForTokenB);\n uint256 nextDiffUsd = Calc.diff(poolParams.nextPoolUsdForTokenA, poolParams.nextPoolUsdForTokenB);\n\n // check whether an improvement in balance comes from causing the balance to switch sides\n // for example, if there is $2000 of ETH and $1000 of USDC in the pool\n // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not\n // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case\n bool isSameSideRebalance = (poolParams.poolUsdForTokenA <= poolParams.poolUsdForTokenB) == (poolParams.nextPoolUsdForTokenA <= poolParams.nextPoolUsdForTokenB);\n uint256 impactExponentFactor = dataStore.getUint(Keys.swapImpactExponentFactorKey(market.marketToken));\n\n bool balanceWasImproved = nextDiffUsd < initialDiffUsd;\n if (isSameSideRebalance) {\n uint256 impactFactor = MarketUtils.getAdjustedSwapImpactFactor(dataStore, market.marketToken, balanceWasImproved);\n\n return (\n PricingUtils.getPriceImpactUsdForSameSideRebalance(\n initialDiffUsd,\n nextDiffUsd,\n impactFactor,\n impactExponentFactor\n ),\n balanceWasImproved\n );\n } else {\n (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedSwapImpactFactors(dataStore, market.marketToken);\n\n return (\n PricingUtils.getPriceImpactUsdForCrossoverRebalance(\n initialDiffUsd,\n nextDiffUsd,\n positiveImpactFactor,\n negativeImpactFactor,\n impactExponentFactor\n ),\n balanceWasImproved\n );\n }\n }\n\n // @dev get the next pool amounts in USD\n // @param params GetPriceImpactUsdParams\n // @return PoolParams\n function getNextPoolAmountsUsd(\n GetPriceImpactUsdParams memory params\n ) internal view returns (PoolParams memory) {\n uint256 poolAmountForTokenA = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenA);\n uint256 poolAmountForTokenB = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenB);\n\n return getNextPoolAmountsParams(\n params,\n poolAmountForTokenA,\n poolAmountForTokenB\n );\n }\n\n function getNextPoolAmountsParams(\n GetPriceImpactUsdParams memory params,\n uint256 poolAmountForTokenA,\n uint256 poolAmountForTokenB\n ) internal pure returns (PoolParams memory) {\n uint256 poolUsdForTokenA = poolAmountForTokenA * params.priceForTokenA;\n uint256 poolUsdForTokenB = poolAmountForTokenB * params.priceForTokenB;\n\n if (params.usdDeltaForTokenA < 0 && (-params.usdDeltaForTokenA).toUint256() > poolUsdForTokenA) {\n revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenA, poolUsdForTokenA);\n }\n\n if (params.usdDeltaForTokenB < 0 && (-params.usdDeltaForTokenB).toUint256() > poolUsdForTokenB) {\n revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenB, poolUsdForTokenB);\n }\n\n uint256 nextPoolUsdForTokenA = Calc.sumReturnUint256(poolUsdForTokenA, params.usdDeltaForTokenA);\n uint256 nextPoolUsdForTokenB = Calc.sumReturnUint256(poolUsdForTokenB, params.usdDeltaForTokenB);\n\n PoolParams memory poolParams = PoolParams(\n poolUsdForTokenA,\n poolUsdForTokenB,\n nextPoolUsdForTokenA,\n nextPoolUsdForTokenB\n );\n\n return poolParams;\n }\n\n // @dev get the swap fees\n // @param dataStore DataStore\n // @param marketToken the address of the market token\n // @param amount the total swap fee amount\n function getSwapFees(\n DataStore dataStore,\n address marketToken,\n uint256 amount,\n bool balanceWasImproved,\n address uiFeeReceiver,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external view returns (SwapFees memory) {\n SwapFees memory fees;\n\n // note that since it is possible to incur both positive and negative price impact values\n // and the negative price impact factor may be larger than the positive impact factor\n // it is possible for the balance to be improved overall but for the price impact to still be negative\n // in this case the fee factor for the **positive** price impact would be charged for the case when priceImpactUsd is negative and balanceWasImproved\n // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue\n uint256 feeFactor;\n\n if (swapPricingType == ISwapPricingUtils.SwapPricingType.Swap) {\n feeFactor = dataStore.getUint(Keys.swapFeeFactorKey(marketToken, balanceWasImproved));\n } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Shift) {\n // empty branch as feeFactor is already zero\n } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.AtomicSwap) {\n feeFactor = dataStore.getUint(Keys.atomicSwapFeeFactorKey(marketToken));\n } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Deposit) {\n feeFactor = dataStore.getUint(Keys.depositFeeFactorKey(marketToken, balanceWasImproved));\n } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Withdrawal) {\n feeFactor = dataStore.getUint(Keys.withdrawalFeeFactorKey(marketToken, balanceWasImproved));\n } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.AtomicWithdrawal) {\n feeFactor = dataStore.getUint(Keys.atomicWithdrawalFeeFactorKey(marketToken));\n }\n\n uint256 swapFeeReceiverFactor = dataStore.getUint(Keys.SWAP_FEE_RECEIVER_FACTOR);\n\n uint256 feeAmount = Precision.applyFactor(amount, feeFactor);\n\n fees.feeReceiverAmount = Precision.applyFactor(feeAmount, swapFeeReceiverFactor);\n fees.feeAmountForPool = feeAmount - fees.feeReceiverAmount;\n\n fees.uiFeeReceiver = uiFeeReceiver;\n fees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);\n fees.uiFeeAmount = Precision.applyFactor(amount, fees.uiFeeReceiverFactor);\n\n fees.amountAfterFees = amount - feeAmount - fees.uiFeeAmount;\n\n return fees;\n }\n\n // note that the priceImpactUsd may not be entirely accurate since it is the\n // base calculation and the actual price impact may be capped by the available\n // amount in the swap impact pool\n function emitSwapInfo(\n EventEmitter eventEmitter,\n EmitSwapInfoParams memory params\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n // orderKey is zero bytes32 for Gelato Relay fee swaps\n eventData.bytes32Items.setItem(0, \"orderKey\", params.orderKey);\n\n eventData.addressItems.initItems(4);\n eventData.addressItems.setItem(0, \"market\", params.market);\n eventData.addressItems.setItem(1, \"receiver\", params.receiver);\n eventData.addressItems.setItem(2, \"tokenIn\", params.tokenIn);\n eventData.addressItems.setItem(3, \"tokenOut\", params.tokenOut);\n\n eventData.uintItems.initItems(5);\n eventData.uintItems.setItem(0, \"tokenInPrice\", params.tokenInPrice);\n eventData.uintItems.setItem(1, \"tokenOutPrice\", params.tokenOutPrice);\n eventData.uintItems.setItem(2, \"amountIn\", params.amountIn);\n // note that amountInAfterFees includes negative price impact\n eventData.uintItems.setItem(3, \"amountInAfterFees\", params.amountInAfterFees);\n eventData.uintItems.setItem(4, \"amountOut\", params.amountOut);\n\n eventData.intItems.initItems(3);\n eventData.intItems.setItem(0, \"priceImpactUsd\", params.priceImpactUsd);\n eventData.intItems.setItem(1, \"priceImpactAmount\", params.priceImpactAmount);\n eventData.intItems.setItem(2, \"tokenInPriceImpactAmount\", params.tokenInPriceImpactAmount);\n\n eventEmitter.emitEventLog1(\n \"SwapInfo\",\n Cast.toBytes32(params.market),\n eventData\n );\n }\n\n function emitSwapFeesCollected(\n EventEmitter eventEmitter,\n bytes32 tradeKey,\n address market,\n address token,\n uint256 tokenPrice,\n bytes32 swapFeeType,\n SwapFees memory fees\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(2);\n eventData.bytes32Items.setItem(0, \"tradeKey\", tradeKey);\n eventData.bytes32Items.setItem(1, \"swapFeeType\", swapFeeType);\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"uiFeeReceiver\", fees.uiFeeReceiver);\n eventData.addressItems.setItem(1, \"market\", market);\n eventData.addressItems.setItem(2, \"token\", token);\n\n eventData.uintItems.initItems(6);\n eventData.uintItems.setItem(0, \"tokenPrice\", tokenPrice);\n eventData.uintItems.setItem(1, \"feeReceiverAmount\", fees.feeReceiverAmount);\n eventData.uintItems.setItem(2, \"feeAmountForPool\", fees.feeAmountForPool);\n eventData.uintItems.setItem(3, \"amountAfterFees\", fees.amountAfterFees);\n eventData.uintItems.setItem(4, \"uiFeeReceiverFactor\", fees.uiFeeReceiverFactor);\n eventData.uintItems.setItem(5, \"uiFeeAmount\", fees.uiFeeAmount);\n\n eventEmitter.emitEventLog1(\n \"SwapFeesCollected\",\n Cast.toBytes32(market),\n eventData\n );\n }\n}\n" + }, + "contracts/reader/GlvReader.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../position/Position.sol\";\n\nimport \"../market/Market.sol\";\nimport \"../price/Price.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../market/Market.sol\";\n\nimport \"../glv/GlvUtils.sol\";\nimport \"../glv/GlvStoreUtils.sol\";\nimport \"../glv/glvDeposit/GlvDepositStoreUtils.sol\";\nimport \"../glv/glvWithdrawal/GlvWithdrawalStoreUtils.sol\";\nimport \"../glv/glvShift/GlvShiftStoreUtils.sol\";\n\n// @title GlvReader\ncontract GlvReader {\n function getGlvValue(\n DataStore dataStore,\n address[] memory marketAddresses,\n Price.Props[] memory indexTokenPrices,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n address glv,\n bool maximize\n ) external view returns (uint256) {\n return\n GlvUtils.getGlvValue(\n dataStore,\n marketAddresses,\n indexTokenPrices,\n longTokenPrice,\n shortTokenPrice,\n glv,\n maximize\n );\n }\n\n function getGlvTokenPrice(\n DataStore dataStore,\n address[] memory marketAddresses,\n Price.Props[] memory indexTokenPrices,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n address glv,\n bool maximize\n ) external view returns (uint256, uint256, uint256) {\n return\n GlvUtils.getGlvTokenPrice(\n dataStore,\n marketAddresses,\n indexTokenPrices,\n longTokenPrice,\n shortTokenPrice,\n glv,\n maximize\n );\n }\n\n function getGlv(DataStore dataStore, address glv) external view returns (Glv.Props memory) {\n return GlvStoreUtils.get(dataStore, glv);\n }\n\n struct GlvInfo {\n Glv.Props glv;\n address[] markets;\n }\n\n function getGlvInfo(DataStore dataStore, address glv) public view returns (GlvInfo memory) {\n bytes32 key = Keys.glvSupportedMarketListKey(glv);\n uint256 count = dataStore.getAddressCount(key);\n address[] memory markets = dataStore.getAddressValuesAt(key, 0, count);\n return GlvInfo({glv: GlvStoreUtils.get(dataStore, glv), markets: markets});\n }\n\n function getGlvBySalt(DataStore dataStore, bytes32 salt) external view returns (Glv.Props memory) {\n return GlvStoreUtils.getBySalt(dataStore, salt);\n }\n\n function getGlvs(DataStore dataStore, uint256 start, uint256 end) external view returns (Glv.Props[] memory) {\n uint256 glvCount = GlvStoreUtils.getGlvCount(dataStore);\n if (end > glvCount) {\n end = glvCount;\n }\n address[] memory glvKeys = GlvStoreUtils.getGlvKeys(dataStore, start, end);\n Glv.Props[] memory glvs = new Glv.Props[](glvKeys.length);\n for (uint256 i; i < glvKeys.length; i++) {\n address glvKey = glvKeys[i];\n Glv.Props memory glv = GlvStoreUtils.get(dataStore, glvKey);\n glvs[i] = glv;\n }\n\n return glvs;\n }\n\n function getGlvInfoList(DataStore dataStore, uint256 start, uint256 end) external view returns (GlvInfo[] memory) {\n uint256 glvCount = GlvStoreUtils.getGlvCount(dataStore);\n if (end > glvCount) {\n end = glvCount;\n }\n address[] memory glvKeys = GlvStoreUtils.getGlvKeys(dataStore, start, end);\n GlvInfo[] memory glvInfoLists = new GlvInfo[](glvKeys.length);\n for (uint256 i; i < glvKeys.length; i++) {\n address glvKey = glvKeys[i];\n glvInfoLists[i] = getGlvInfo(dataStore, glvKey);\n }\n\n return glvInfoLists;\n }\n\n function getGlvDeposit(DataStore dataStore, bytes32 key) external view returns (GlvDeposit.Props memory) {\n return GlvDepositStoreUtils.get(dataStore, key);\n }\n\n function getGlvDeposits(\n DataStore dataStore,\n uint256 start,\n uint256 end\n ) external view returns (GlvDeposit.Props[] memory) {\n bytes32[] memory glvDepositKeys = GlvDepositStoreUtils.getGlvDepositKeys(dataStore, start, end);\n GlvDeposit.Props[] memory glvDeposits = new GlvDeposit.Props[](glvDepositKeys.length);\n for (uint256 i; i < glvDepositKeys.length; i++) {\n bytes32 glvDepositKey = glvDepositKeys[i];\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(dataStore, glvDepositKey);\n glvDeposits[i] = glvDeposit;\n }\n\n return glvDeposits;\n }\n\n function getAccountGlvDeposits(\n DataStore dataStore,\n address account,\n uint256 start,\n uint256 end\n ) external view returns (GlvDeposit.Props[] memory) {\n bytes32[] memory glvDepositKeys = GlvDepositStoreUtils.getAccountGlvDepositKeys(dataStore, account, start, end);\n GlvDeposit.Props[] memory glvDeposits = new GlvDeposit.Props[](glvDepositKeys.length);\n for (uint256 i; i < glvDepositKeys.length; i++) {\n bytes32 glvDepositKey = glvDepositKeys[i];\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(dataStore, glvDepositKey);\n glvDeposits[i] = glvDeposit;\n }\n\n return glvDeposits;\n }\n\n function getGlvWithdrawal(DataStore dataStore, bytes32 key) external view returns (GlvWithdrawal.Props memory) {\n return GlvWithdrawalStoreUtils.get(dataStore, key);\n }\n\n function getGlvWithdrawals(\n DataStore dataStore,\n uint256 start,\n uint256 end\n ) external view returns (GlvWithdrawal.Props[] memory) {\n bytes32[] memory glvWithdrawalKeys = GlvWithdrawalStoreUtils.getGlvWithdrawalKeys(dataStore, start, end);\n GlvWithdrawal.Props[] memory glvWithdrawals = new GlvWithdrawal.Props[](glvWithdrawalKeys.length);\n for (uint256 i; i < glvWithdrawalKeys.length; i++) {\n bytes32 glvWithdrawalKey = glvWithdrawalKeys[i];\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(dataStore, glvWithdrawalKey);\n glvWithdrawals[i] = glvWithdrawal;\n }\n\n return glvWithdrawals;\n }\n\n function getAccountGlvWithdrawals(\n DataStore dataStore,\n address account,\n uint256 start,\n uint256 end\n ) external view returns (GlvWithdrawal.Props[] memory) {\n bytes32[] memory glvWithdrawalKeys = GlvWithdrawalStoreUtils.getAccountGlvWithdrawalKeys(\n dataStore,\n account,\n start,\n end\n );\n GlvWithdrawal.Props[] memory glvWithdrawals = new GlvWithdrawal.Props[](glvWithdrawalKeys.length);\n for (uint256 i; i < glvWithdrawalKeys.length; i++) {\n bytes32 glvWithdrawalKey = glvWithdrawalKeys[i];\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(dataStore, glvWithdrawalKey);\n glvWithdrawals[i] = glvWithdrawal;\n }\n\n return glvWithdrawals;\n }\n\n function getGlvShift(DataStore dataStore, bytes32 key) external view returns (GlvShift.Props memory) {\n return GlvShiftStoreUtils.get(dataStore, key);\n }\n\n function getGlvShifts(\n DataStore dataStore,\n uint256 start,\n uint256 end\n ) external view returns (GlvShift.Props[] memory) {\n bytes32[] memory glvShiftKeys = GlvShiftStoreUtils.getGlvShiftKeys(dataStore, start, end);\n GlvShift.Props[] memory glvShifts = new GlvShift.Props[](glvShiftKeys.length);\n for (uint256 i; i < glvShiftKeys.length; i++) {\n bytes32 glvShiftKey = glvShiftKeys[i];\n GlvShift.Props memory glvShift = GlvShiftStoreUtils.get(dataStore, glvShiftKey);\n glvShifts[i] = glvShift;\n }\n\n return glvShifts;\n }\n}\n" + }, + "contracts/reader/KeeperReader.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../position/Position.sol\";\nimport \"../position/PositionStoreUtils.sol\";\n\nimport \"../order/OrderStoreUtils.sol\";\n\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\n\nimport \"../referral/IReferralStorage.sol\";\n\n// @title KeeperReader\n// @dev Library for read functions\ncontract KeeperReader {\n function getOrders(DataStore dataStore, uint256 start, uint256 end) external view returns (Order.Props[] memory) {\n bytes32[] memory orderKeys = OrderStoreUtils.getOrderKeys(dataStore, start, end);\n Order.Props[] memory orders = new Order.Props[](orderKeys.length);\n for (uint256 i; i < orderKeys.length; i++) {\n bytes32 orderKey = orderKeys[i];\n orders[i] = OrderStoreUtils.get(dataStore, orderKey);\n }\n return orders;\n }\n\n /* function getLiquidatablePositions(\n DataStore dataStore,\n IReferralStorage referralStorage,\n MarketUtils.MarketPrices[] memory marketPrices,\n uint256 start,\n uint256 end,\n bool shouldValidateMinCollateralUsd\n ) external view returns (bytes32[] memory) {\n\n } */\n\n // bytes32[] memory positionKeys = PositionStoreUtils.getAccountPositionKeys(dataStore, account, start, end);\n // Position.Props[] memory positions = new Position.Props[](positionKeys.length);\n // for (uint256 i; i < positionKeys.length; i++) {\n // bytes32 positionKey = positionKeys[i];\n // positions[i] = PositionStoreUtils.get(dataStore, positionKey);\n // }\n\n // return positions;\n}\n" + }, + "contracts/reader/Reader.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../market/MarketStoreUtils.sol\";\n\nimport \"../deposit/DepositStoreUtils.sol\";\nimport \"../withdrawal/WithdrawalStoreUtils.sol\";\nimport \"../shift/ShiftStoreUtils.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../position/PositionUtils.sol\";\nimport \"../position/PositionStoreUtils.sol\";\n\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\n\nimport \"./ReaderUtils.sol\";\nimport \"./ReaderDepositUtils.sol\";\nimport \"./ReaderWithdrawalUtils.sol\";\nimport \"./ReaderPositionUtils.sol\";\n\n// @title Reader\n// @dev Library for read functions\ncontract Reader {\n using SafeCast for uint256;\n using Position for Position.Props;\n\n function getMarket(DataStore dataStore, address key) external view returns (Market.Props memory) {\n return MarketStoreUtils.get(dataStore, key);\n }\n\n function getMarketBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {\n return MarketStoreUtils.getBySalt(dataStore, salt);\n }\n\n function getDeposit(DataStore dataStore, bytes32 key) external view returns (Deposit.Props memory) {\n return DepositStoreUtils.get(dataStore, key);\n }\n\n function getWithdrawal(DataStore dataStore, bytes32 key) external view returns (Withdrawal.Props memory) {\n return WithdrawalStoreUtils.get(dataStore, key);\n }\n\n function getShift(DataStore dataStore, bytes32 key) external view returns (Shift.Props memory) {\n return ShiftStoreUtils.get(dataStore, key);\n }\n\n function getPosition(DataStore dataStore, bytes32 key) external view returns (Position.Props memory) {\n return PositionStoreUtils.get(dataStore, key);\n }\n\n function getOrder(DataStore dataStore, bytes32 key) external view returns (Order.Props memory) {\n return ReaderUtils.getOrder(dataStore, key);\n }\n\n function getPositionPnlUsd(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n bytes32 positionKey,\n uint256 sizeDeltaUsd\n ) external view returns (int256, int256, uint256) {\n Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey);\n\n return PositionUtils.getPositionPnlUsd(dataStore, market, prices, position, sizeDeltaUsd);\n }\n\n function getAccountPositions(\n DataStore dataStore,\n address account,\n uint256 start,\n uint256 end\n ) external view returns (Position.Props[] memory) {\n return ReaderPositionUtils.getAccountPositions(dataStore, account, start, end);\n }\n\n function getPositionInfo(\n DataStore dataStore,\n IReferralStorage referralStorage,\n bytes32 positionKey,\n MarketUtils.MarketPrices memory prices,\n uint256 sizeDeltaUsd,\n address uiFeeReceiver,\n bool usePositionSizeAsSizeDeltaUsd\n ) public view returns (ReaderPositionUtils.PositionInfo memory) {\n return\n ReaderPositionUtils.getPositionInfo(\n dataStore,\n referralStorage,\n positionKey,\n prices,\n sizeDeltaUsd,\n uiFeeReceiver,\n usePositionSizeAsSizeDeltaUsd\n );\n }\n\n function getPositionInfoList(\n DataStore dataStore,\n IReferralStorage referralStorage,\n bytes32[] memory positionKeys,\n MarketUtils.MarketPrices[] memory prices,\n address uiFeeReceiver\n ) external view returns (ReaderPositionUtils.PositionInfo[] memory) {\n return\n ReaderPositionUtils.getPositionInfoList(\n dataStore,\n referralStorage,\n positionKeys,\n prices,\n uiFeeReceiver\n );\n }\n\n // `markets` and `marketPrices` should contain perp markets only\n function getAccountPositionInfoList(\n DataStore dataStore,\n IReferralStorage referralStorage,\n address account,\n address[] memory markets,\n MarketUtils.MarketPrices[] memory marketPrices,\n address uiFeeReceiver,\n uint256 start,\n uint256 end\n ) external view returns (ReaderPositionUtils.PositionInfo[] memory) {\n return\n ReaderPositionUtils.getAccountPositionInfoList(\n dataStore,\n referralStorage,\n account,\n markets,\n marketPrices,\n uiFeeReceiver,\n start,\n end\n );\n }\n\n function isPositionLiquidatable(\n DataStore dataStore,\n IReferralStorage referralStorage,\n bytes32 positionKey,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n bool shouldValidateMinCollateralUsd,\n bool forLiquidation\n ) public view returns (bool, string memory, PositionUtils.IsPositionLiquidatableInfo memory) {\n Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey);\n\n return\n PositionUtils.isPositionLiquidatable(\n dataStore,\n referralStorage,\n position,\n market,\n prices,\n shouldValidateMinCollateralUsd,\n forLiquidation\n );\n }\n\n function getAccountOrders(\n DataStore dataStore,\n address account,\n uint256 start,\n uint256 end\n ) external view returns (ReaderUtils.OrderInfo[] memory) {\n return ReaderUtils.getAccountOrders(dataStore, account, start, end);\n }\n\n function getMarkets(DataStore dataStore, uint256 start, uint256 end) external view returns (Market.Props[] memory) {\n return ReaderUtils.getMarkets(dataStore, start, end);\n }\n\n function getMarketInfoList(\n DataStore dataStore,\n MarketUtils.MarketPrices[] memory marketPricesList,\n uint256 start,\n uint256 end\n ) external view returns (ReaderUtils.MarketInfo[] memory) {\n return ReaderUtils.getMarketInfoList(dataStore, marketPricesList, start, end);\n }\n\n function getMarketInfo(\n DataStore dataStore,\n MarketUtils.MarketPrices memory prices,\n address marketKey\n ) public view returns (ReaderUtils.MarketInfo memory) {\n return ReaderUtils.getMarketInfo(dataStore, prices, marketKey);\n }\n\n function getMarketTokenPrice(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n Price.Props memory longTokenPrice,\n Price.Props memory shortTokenPrice,\n bytes32 pnlFactorType,\n bool maximize\n ) external view returns (int256, MarketPoolValueInfo.Props memory) {\n return\n MarketUtils.getMarketTokenPrice(\n dataStore,\n market,\n indexTokenPrice,\n longTokenPrice,\n shortTokenPrice,\n pnlFactorType,\n maximize\n );\n }\n\n function getPendingPositionImpactPoolDistributionAmount(\n DataStore dataStore,\n address market\n ) external view returns (uint256, uint256) {\n return MarketUtils.getPendingPositionImpactPoolDistributionAmount(dataStore, market);\n }\n\n function getNetPnl(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n bool maximize\n ) external view returns (int256) {\n return MarketUtils.getNetPnl(dataStore, market, indexTokenPrice, maximize);\n }\n\n function getPnl(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n bool isLong,\n bool maximize\n ) external view returns (int256) {\n return MarketUtils.getPnl(dataStore, market, indexTokenPrice, isLong, maximize);\n }\n\n function getOpenInterestWithPnl(\n DataStore dataStore,\n Market.Props memory market,\n Price.Props memory indexTokenPrice,\n bool isLong,\n bool maximize\n ) external view returns (int256) {\n return MarketUtils.getOpenInterestWithPnl(dataStore, market, indexTokenPrice, isLong, maximize);\n }\n\n function getPnlToPoolFactor(\n DataStore dataStore,\n address marketAddress,\n MarketUtils.MarketPrices memory prices,\n bool isLong,\n bool maximize\n ) external view returns (int256) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);\n return MarketUtils.getPnlToPoolFactor(dataStore, market, prices, isLong, maximize);\n }\n\n function getSwapAmountOut(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n address tokenIn,\n uint256 amountIn,\n address uiFeeReceiver\n ) external view returns (uint256, int256, SwapPricingUtils.SwapFees memory fees) {\n return ReaderPricingUtils.getSwapAmountOut(dataStore, market, prices, tokenIn, amountIn, uiFeeReceiver);\n }\n\n function getExecutionPrice(\n DataStore dataStore,\n address marketKey,\n MarketUtils.MarketPrices memory prices,\n uint256 positionSizeInUsd,\n uint256 positionSizeInTokens,\n int256 sizeDeltaUsd,\n int256 pendingImpactAmount,\n bool isLong\n ) external view returns (ReaderPricingUtils.ExecutionPriceResult memory) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);\n return\n ReaderPricingUtils.getExecutionPrice(\n dataStore,\n market,\n prices,\n positionSizeInUsd,\n positionSizeInTokens,\n sizeDeltaUsd,\n pendingImpactAmount,\n isLong\n );\n }\n\n function getSwapPriceImpact(\n DataStore dataStore,\n address marketKey,\n address tokenIn,\n address tokenOut,\n uint256 amountIn,\n Price.Props memory tokenInPrice,\n Price.Props memory tokenOutPrice\n ) external view returns (int256, int256, int256) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);\n return\n ReaderPricingUtils.getSwapPriceImpact(\n dataStore,\n market,\n tokenIn,\n tokenOut,\n amountIn,\n tokenInPrice,\n tokenOutPrice\n );\n }\n\n function getAdlState(\n DataStore dataStore,\n address market,\n bool isLong,\n MarketUtils.MarketPrices memory prices\n ) external view returns (uint256, bool, int256, uint256) {\n return ReaderUtils.getAdlState(dataStore, market, isLong, prices);\n }\n\n function getDepositAmountOut(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n uint256 longTokenAmount,\n uint256 shortTokenAmount,\n address uiFeeReceiver,\n ISwapPricingUtils.SwapPricingType swapPricingType,\n bool includeVirtualInventoryImpact\n ) external view returns (uint256) {\n return\n ReaderDepositUtils.getDepositAmountOut(\n dataStore,\n market,\n prices,\n longTokenAmount,\n shortTokenAmount,\n uiFeeReceiver,\n swapPricingType,\n includeVirtualInventoryImpact\n );\n }\n\n function getWithdrawalAmountOut(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n uint256 marketTokenAmount,\n address uiFeeReceiver,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external view returns (uint256, uint256) {\n return\n ReaderWithdrawalUtils.getWithdrawalAmountOut(\n dataStore,\n market,\n prices,\n marketTokenAmount,\n uiFeeReceiver,\n swapPricingType\n );\n }\n}\n" + }, + "contracts/reader/ReaderDepositUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\nimport \"../data/Keys.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\n\nimport \"../pricing/ISwapPricingUtils.sol\";\nimport \"../pricing/SwapPricingUtils.sol\";\n\nlibrary ReaderDepositUtils {\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n using Price for Price.Props;\n using Position for Position.Props;\n using Order for Order.Props;\n\n struct GetDepositAmountOutForSingleTokenParams {\n DataStore dataStore;\n Market.Props market;\n MarketUtils.MarketPrices prices;\n address tokenIn;\n Price.Props tokenInPrice;\n address tokenOut;\n Price.Props tokenOutPrice;\n uint256 amount;\n int256 priceImpactUsd;\n address uiFeeReceiver;\n ISwapPricingUtils.SwapPricingType swapPricingType;\n }\n\n struct GetDepositAmountOutCache {\n int256 priceImpactUsd;\n bool balanceWasImproved;\n }\n\n function getDepositAmountOut(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n uint256 longTokenAmount,\n uint256 shortTokenAmount,\n address uiFeeReceiver,\n ISwapPricingUtils.SwapPricingType swapPricingType,\n bool includeVirtualInventoryImpact\n ) external view returns (uint256) {\n uint256 longTokenUsd = longTokenAmount * prices.longTokenPrice.midPrice();\n uint256 shortTokenUsd = shortTokenAmount * prices.shortTokenPrice.midPrice();\n GetDepositAmountOutCache memory cache;\n (cache.priceImpactUsd, cache.balanceWasImproved) = SwapPricingUtils.getPriceImpactUsd(\n SwapPricingUtils.GetPriceImpactUsdParams(\n dataStore,\n market,\n market.longToken,\n market.shortToken,\n prices.longTokenPrice.midPrice(),\n prices.shortTokenPrice.midPrice(),\n longTokenUsd.toInt256(),\n shortTokenUsd.toInt256(),\n includeVirtualInventoryImpact\n )\n );\n\n uint256 mintAmount;\n\n mintAmount += getDepositAmountOutForSingleToken(\n GetDepositAmountOutForSingleTokenParams(\n dataStore,\n market,\n prices,\n market.longToken,\n prices.longTokenPrice,\n market.shortToken,\n prices.shortTokenPrice,\n longTokenAmount,\n Precision.mulDiv(cache.priceImpactUsd, longTokenUsd, longTokenUsd + shortTokenUsd),\n uiFeeReceiver,\n swapPricingType\n ),\n cache.balanceWasImproved\n );\n\n mintAmount += getDepositAmountOutForSingleToken(\n GetDepositAmountOutForSingleTokenParams(\n dataStore,\n market,\n prices,\n market.shortToken,\n prices.shortTokenPrice,\n market.longToken,\n prices.longTokenPrice,\n shortTokenAmount,\n Precision.mulDiv(cache.priceImpactUsd, shortTokenUsd, longTokenUsd + shortTokenUsd),\n uiFeeReceiver,\n swapPricingType\n ),\n cache.balanceWasImproved\n );\n\n return mintAmount;\n }\n\n function getDepositAmountOutForSingleToken(\n GetDepositAmountOutForSingleTokenParams memory params,\n bool balanceWasImproved\n ) public view returns (uint256) {\n SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(\n params.dataStore,\n params.market.marketToken,\n params.amount,\n balanceWasImproved, // balanceWasImproved\n params.uiFeeReceiver, // uiFeeReceiver\n params.swapPricingType\n );\n\n uint256 mintAmount;\n uint256 amountIn = fees.amountAfterFees;\n\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n params.market,\n params.prices.indexTokenPrice,\n params.prices.longTokenPrice,\n params.prices.shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,\n true\n );\n\n if (poolValueInfo.poolValue < 0) {\n revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);\n }\n\n uint256 poolValue = poolValueInfo.poolValue.toUint256();\n\n uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(params.market.marketToken)));\n\n if (poolValueInfo.poolValue == 0 && marketTokensSupply > 0) {\n revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);\n }\n\n if (params.priceImpactUsd > 0 && marketTokensSupply == 0) {\n params.priceImpactUsd = 0;\n }\n\n if (params.priceImpactUsd > 0) {\n (int256 positiveImpactAmount, uint256 cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap(\n params.dataStore,\n params.market.marketToken,\n params.tokenOut,\n params.tokenOutPrice,\n params.priceImpactUsd\n );\n\n mintAmount += MarketUtils.usdToMarketTokenAmount(\n positiveImpactAmount.toUint256() * params.tokenOutPrice.max,\n poolValue,\n marketTokensSupply\n );\n\n if (cappedDiffUsd != 0) {\n (int256 tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(\n params.dataStore,\n params.market.marketToken,\n params.tokenIn,\n params.tokenInPrice,\n cappedDiffUsd.toInt256()\n );\n\n amountIn += tokenInPriceImpactAmount.toUint256();\n }\n }\n\n if (params.priceImpactUsd < 0) {\n (int256 negativeImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(\n params.dataStore,\n params.market.marketToken,\n params.tokenIn,\n params.tokenInPrice,\n params.priceImpactUsd\n );\n\n amountIn -= (-negativeImpactAmount).toUint256();\n }\n\n mintAmount += MarketUtils.usdToMarketTokenAmount(\n amountIn * params.tokenInPrice.min,\n poolValue,\n marketTokensSupply\n );\n\n return mintAmount;\n }\n}\n" + }, + "contracts/reader/ReaderPositionUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../market/MarketStoreUtils.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../position/PositionUtils.sol\";\nimport \"../position/PositionStoreUtils.sol\";\n\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\nimport \"./ReaderPricingUtils.sol\";\n\nlibrary ReaderPositionUtils {\n using Position for Position.Props;\n using SafeCast for uint256;\n\n struct PositionInfo {\n bytes32 positionKey;\n Position.Props position;\n PositionPricingUtils.PositionFees fees;\n ReaderPricingUtils.ExecutionPriceResult executionPriceResult;\n int256 basePnlUsd;\n int256 uncappedBasePnlUsd;\n int256 pnlAfterPriceImpactUsd;\n }\n\n struct GetPositionInfoCache {\n Market.Props market;\n Price.Props collateralTokenPrice;\n uint256 pendingBorrowingFeeUsd;\n }\n\n function getNextBorrowingFees(\n DataStore dataStore,\n Position.Props memory position,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices\n ) internal view returns (uint256) {\n return MarketUtils.getNextBorrowingFees(\n dataStore,\n position,\n market,\n prices\n );\n }\n\n function getBorrowingFees(\n DataStore dataStore,\n Price.Props memory collateralTokenPrice,\n uint256 borrowingFeeUsd\n ) internal view returns (PositionPricingUtils.PositionBorrowingFees memory) {\n return PositionPricingUtils.getBorrowingFees(\n dataStore,\n collateralTokenPrice,\n borrowingFeeUsd\n );\n }\n\n function getPositionInfoList(\n DataStore dataStore,\n IReferralStorage referralStorage,\n bytes32[] memory positionKeys,\n MarketUtils.MarketPrices[] memory prices,\n address uiFeeReceiver\n ) external view returns (ReaderPositionUtils.PositionInfo[] memory) {\n ReaderPositionUtils.PositionInfo[] memory positionInfoList = new ReaderPositionUtils.PositionInfo[](positionKeys.length);\n for (uint256 i; i < positionKeys.length; i++) {\n bytes32 positionKey = positionKeys[i];\n positionInfoList[i] = getPositionInfo(\n dataStore,\n referralStorage,\n positionKey,\n prices[i],\n 0, // sizeDeltaUsd\n uiFeeReceiver,\n true // usePositionSizeAsSizeDeltaUsd\n );\n positionInfoList[i].positionKey = positionKey;\n }\n\n return positionInfoList;\n }\n\n function getAccountPositionInfoList(\n DataStore dataStore,\n IReferralStorage referralStorage,\n address account,\n address[] memory markets,\n MarketUtils.MarketPrices[] memory marketPrices,\n address uiFeeReceiver,\n uint256 start,\n uint256 end\n ) external view returns (ReaderPositionUtils.PositionInfo[] memory) {\n bytes32[] memory positionKeys = PositionStoreUtils.getAccountPositionKeys(dataStore, account, start, end);\n ReaderPositionUtils.PositionInfo[] memory positionInfoList = new ReaderPositionUtils.PositionInfo[](positionKeys.length);\n for (uint256 i; i < positionKeys.length; i++) {\n bytes32 positionKey = positionKeys[i];\n Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey);\n MarketUtils.MarketPrices memory prices = _getMarketPricesByAddress(markets, marketPrices, position.market());\n positionInfoList[i] = getPositionInfo(\n dataStore,\n referralStorage,\n position,\n prices,\n 0, // sizeDeltaUsd\n uiFeeReceiver,\n true // usePositionSizeAsSizeDeltaUsd\n );\n positionInfoList[i].positionKey = positionKey;\n }\n\n return positionInfoList;\n }\n\n function _getMarketPricesByAddress(\n address[] memory markets,\n MarketUtils.MarketPrices[] memory marketPrices,\n address market\n ) internal pure returns (MarketUtils.MarketPrices memory) {\n for (uint256 i = 0; i < markets.length; i++) {\n address currentMarket = markets[i];\n if (currentMarket == market) {\n return marketPrices[i];\n }\n }\n\n revert Errors.EmptyMarketPrice(market);\n }\n\n function getNextFundingAmountPerSize(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices\n ) public view returns (MarketUtils.GetNextFundingAmountPerSizeResult memory) {\n return MarketUtils.getNextFundingAmountPerSize(\n dataStore,\n market,\n prices\n );\n }\n\n function getAccountPositions(\n DataStore dataStore,\n address account,\n uint256 start,\n uint256 end\n ) external view returns (Position.Props[] memory) {\n bytes32[] memory positionKeys = PositionStoreUtils.getAccountPositionKeys(dataStore, account, start, end);\n Position.Props[] memory positions = new Position.Props[](positionKeys.length);\n for (uint256 i; i < positionKeys.length; i++) {\n bytes32 positionKey = positionKeys[i];\n positions[i] = PositionStoreUtils.get(dataStore, positionKey);\n }\n\n return positions;\n }\n\n function getPositionInfo(\n DataStore dataStore,\n IReferralStorage referralStorage,\n bytes32 positionKey,\n MarketUtils.MarketPrices memory prices,\n uint256 sizeDeltaUsd,\n address uiFeeReceiver,\n bool usePositionSizeAsSizeDeltaUsd\n ) public view returns (PositionInfo memory) {\n Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey);\n return getPositionInfo(\n dataStore,\n referralStorage,\n position,\n prices,\n sizeDeltaUsd,\n uiFeeReceiver,\n usePositionSizeAsSizeDeltaUsd\n );\n }\n\n function getPositionInfo(\n DataStore dataStore,\n IReferralStorage referralStorage,\n Position.Props memory position,\n MarketUtils.MarketPrices memory prices,\n uint256 sizeDeltaUsd,\n address uiFeeReceiver,\n bool usePositionSizeAsSizeDeltaUsd\n ) internal view returns (PositionInfo memory) {\n if (position.account() == address(0)) {\n revert Errors.EmptyPosition();\n }\n\n PositionInfo memory positionInfo;\n GetPositionInfoCache memory cache;\n\n positionInfo.position = position;\n cache.market = MarketStoreUtils.get(dataStore, positionInfo.position.market());\n cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(positionInfo.position.collateralToken(), cache.market, prices);\n\n if (usePositionSizeAsSizeDeltaUsd) {\n sizeDeltaUsd = positionInfo.position.sizeInUsd();\n }\n\n positionInfo.executionPriceResult = ReaderPricingUtils.getExecutionPrice(\n dataStore,\n cache.market,\n prices,\n positionInfo.position.sizeInUsd(),\n positionInfo.position.sizeInTokens(),\n -sizeDeltaUsd.toInt256(),\n positionInfo.position.pendingImpactAmount(),\n positionInfo.position.isLong()\n );\n\n PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams({\n dataStore: dataStore,\n referralStorage: referralStorage,\n position: positionInfo.position,\n collateralTokenPrice: cache.collateralTokenPrice,\n balanceWasImproved: positionInfo.executionPriceResult.balanceWasImproved,\n longToken: cache.market.longToken,\n shortToken: cache.market.shortToken,\n sizeDeltaUsd: sizeDeltaUsd,\n uiFeeReceiver: uiFeeReceiver,\n isLiquidation: false\n });\n\n positionInfo.fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);\n\n // borrowing and funding fees need to be overwritten with pending values otherwise they\n // would be using storage values that have not yet been updated\n cache.pendingBorrowingFeeUsd = getNextBorrowingFees(dataStore, positionInfo.position, cache.market, prices);\n\n positionInfo.fees.borrowing = getBorrowingFees(\n dataStore,\n cache.collateralTokenPrice,\n cache.pendingBorrowingFeeUsd\n );\n\n MarketUtils.GetNextFundingAmountPerSizeResult memory nextFundingAmountResult = getNextFundingAmountPerSize(dataStore, cache.market, prices);\n\n positionInfo.fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(\n dataStore,\n positionInfo.position.market(),\n positionInfo.position.collateralToken(),\n positionInfo.position.isLong()\n );\n\n positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\n dataStore,\n positionInfo.position.market(),\n cache.market.longToken,\n positionInfo.position.isLong()\n );\n\n positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(\n dataStore,\n positionInfo.position.market(),\n cache.market.shortToken,\n positionInfo.position.isLong()\n );\n\n // see MarketUtils.getNextFundingAmountPerSize for more info on why this multiplier is needed\n // a short summary:\n // - funding values are split based on long and short token\n // - for single token markets, these tokens are the same\n // - so when the funding values are applied in updateFundingState, they are applied twice\n // - e.g.\n // - increase fundingFeeAmountPerSize(market, collateralToken: token0, isLong: true) by 10\n // - increase fundingFeeAmountPerSize(market, collateralToken: token1, isLong: true) by 10\n // - for a single token market, token0 is the same as token1, so the value would be increased by 20\n // - to avoid costs being doubled, these values are halved in MarketUtils.getNextFundingAmountPerSize\n // - the reader code needs to double the values, because in the code below the nextFundingAmountResult\n // values are applied virtually instead of the DataStore values being updated\n uint256 multiplier = cache.market.longToken == cache.market.shortToken ? 2 : 1;\n\n if (positionInfo.position.isLong()) {\n positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.long.longToken * multiplier;\n positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.long.shortToken * multiplier;\n\n if (positionInfo.position.collateralToken() == cache.market.longToken) {\n positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.long.longToken * multiplier;\n } else {\n positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.long.shortToken * multiplier;\n }\n } else {\n positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.short.longToken * multiplier;\n positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.short.shortToken * multiplier;\n\n if (positionInfo.position.collateralToken() == cache.market.longToken) {\n positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.short.longToken * multiplier;\n } else {\n positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.short.shortToken * multiplier;\n }\n }\n\n positionInfo.fees.funding = PositionPricingUtils.getFundingFees(\n positionInfo.fees.funding,\n positionInfo.position\n );\n\n (positionInfo.basePnlUsd, positionInfo.uncappedBasePnlUsd, /* sizeDeltaInTokens */) = PositionUtils.getPositionPnlUsd(\n dataStore,\n cache.market,\n prices,\n positionInfo.position,\n sizeDeltaUsd\n );\n\n // with totalImpactUsd the pnlAfterPriceImpactUsd may not be a very useful value to return and may be deprecated in a future iteration\n positionInfo.pnlAfterPriceImpactUsd = positionInfo.executionPriceResult.priceImpactUsd + positionInfo.basePnlUsd;\n\n positionInfo.fees.totalCostAmountExcludingFunding =\n positionInfo.fees.positionFeeAmount\n + positionInfo.fees.borrowing.borrowingFeeAmount\n + positionInfo.fees.ui.uiFeeAmount\n - positionInfo.fees.totalDiscountAmount;\n\n positionInfo.fees.totalCostAmount =\n positionInfo.fees.totalCostAmountExcludingFunding\n + positionInfo.fees.funding.fundingFeeAmount;\n\n return positionInfo;\n }\n}\n" + }, + "contracts/reader/ReaderPricingUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../position/PositionUtils.sol\";\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\nimport \"../pricing/SwapPricingUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\n\n// @title ReaderPricingUtils\nlibrary ReaderPricingUtils {\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n using Price for Price.Props;\n using Position for Position.Props;\n using Order for Order.Props;\n\n struct ExecutionPriceResult {\n int256 priceImpactUsd;\n uint256 executionPrice;\n bool balanceWasImproved;\n int256 proportionalPendingImpactUsd;\n int256 totalImpactUsd;\n uint256 priceImpactDiffUsd;\n }\n\n // returns amountOut, price impact, fees\n function getSwapAmountOut(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n address tokenIn,\n uint256 amountIn,\n address uiFeeReceiver\n ) external view returns (uint256, int256, SwapPricingUtils.SwapFees memory) {\n SwapUtils.SwapCache memory cache;\n\n if (tokenIn != market.longToken && tokenIn != market.shortToken) {\n revert Errors.InvalidTokenIn(tokenIn, market.marketToken);\n }\n\n MarketUtils.validateSwapMarket(dataStore, market);\n\n cache.tokenOut = MarketUtils.getOppositeToken(tokenIn, market);\n cache.tokenInPrice = MarketUtils.getCachedTokenPrice(tokenIn, market, prices);\n cache.tokenOutPrice = MarketUtils.getCachedTokenPrice(cache.tokenOut, market, prices);\n\n (int256 priceImpactUsd, bool balanceWasImproved) = SwapPricingUtils.getPriceImpactUsd(\n SwapPricingUtils.GetPriceImpactUsdParams(\n dataStore,\n market,\n tokenIn,\n cache.tokenOut,\n cache.tokenInPrice.midPrice(),\n cache.tokenOutPrice.midPrice(),\n (amountIn * cache.tokenInPrice.midPrice()).toInt256(),\n -(amountIn * cache.tokenInPrice.midPrice()).toInt256(),\n true // includeVirtualInventoryImpact\n )\n );\n\n SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(\n dataStore,\n market.marketToken,\n amountIn,\n balanceWasImproved,\n uiFeeReceiver,\n ISwapPricingUtils.SwapPricingType.Swap\n );\n\n int256 impactAmount;\n\n if (priceImpactUsd > 0) {\n // when there is a positive price impact factor, additional tokens from the swap impact pool\n // are withdrawn for the user\n // for example, if 50,000 USDC is swapped out and there is a positive price impact\n // an additional 100 USDC may be sent to the user\n // the swap impact pool is decreased by the used amount\n\n cache.amountIn = fees.amountAfterFees;\n\n (impactAmount, cache.cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap(\n dataStore,\n market.marketToken,\n cache.tokenOut,\n cache.tokenOutPrice,\n priceImpactUsd\n );\n\n if (cache.cappedDiffUsd != 0) {\n (cache.tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(\n dataStore,\n market.marketToken,\n tokenIn,\n cache.tokenInPrice,\n cache.cappedDiffUsd.toInt256()\n );\n\n // this additional amountIn is already in the Market\n // it is subtracted from the swap impact pool amount\n // and the market pool amount is increased by the updated\n // amountIn below\n cache.amountIn += cache.tokenInPriceImpactAmount.toUint256();\n }\n\n // round amountOut down\n cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;\n cache.poolAmountOut = cache.amountOut;\n\n cache.amountOut += impactAmount.toUint256();\n } else {\n // when there is a negative price impact factor,\n // less of the input amount is sent to the pool\n // for example, if 10 ETH is swapped in and there is a negative price impact\n // only 9.995 ETH may be swapped in\n // the remaining 0.005 ETH will be stored in the swap impact pool\n\n (impactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(\n dataStore,\n market.marketToken,\n tokenIn,\n cache.tokenInPrice,\n priceImpactUsd\n );\n\n cache.amountIn = fees.amountAfterFees - (-impactAmount).toUint256();\n cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;\n cache.poolAmountOut = cache.amountOut;\n }\n\n return (cache.amountOut, impactAmount, fees);\n }\n\n function getExecutionPrice(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n uint256 positionSizeInUsd,\n uint256 positionSizeInTokens,\n int256 sizeDeltaUsd,\n int256 pendingImpactAmount,\n bool isLong\n ) external view returns (ExecutionPriceResult memory) {\n PositionUtils.UpdatePositionParams memory params;\n\n params.contracts.dataStore = dataStore;\n params.market = market;\n\n params.order.setSizeDeltaUsd(sizeDeltaUsd.abs());\n params.order.setIsLong(isLong);\n\n bool isIncrease = sizeDeltaUsd > 0;\n bool shouldExecutionPriceBeSmaller = isIncrease ? isLong : !isLong;\n params.order.setAcceptablePrice(shouldExecutionPriceBeSmaller ? type(uint256).max : 0);\n\n params.position.setSizeInUsd(positionSizeInUsd);\n params.position.setSizeInTokens(positionSizeInTokens);\n params.position.setIsLong(isLong);\n params.position.setPendingImpactAmount(pendingImpactAmount);\n\n ExecutionPriceResult memory result;\n\n if (sizeDeltaUsd > 0) {\n (result.priceImpactUsd, /* priceImpactAmount */, /* sizeDeltaInTokens */, result.executionPrice, result.balanceWasImproved) = PositionUtils.getExecutionPriceForIncrease(\n params,\n prices\n );\n } else {\n (result.priceImpactUsd, result.executionPrice, result.balanceWasImproved) = PositionUtils.getExecutionPriceForDecrease(\n params,\n prices.indexTokenPrice\n );\n\n result.proportionalPendingImpactUsd = _getProportionalPendingImpactValues(\n params.position.sizeInUsd(),\n params.position.pendingImpactAmount(),\n params.order.sizeDeltaUsd(),\n prices.indexTokenPrice\n );\n\n result.totalImpactUsd = result.proportionalPendingImpactUsd + result.priceImpactUsd;\n\n if (result.totalImpactUsd < 0) {\n uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactor(\n dataStore,\n market.marketToken,\n false\n );\n\n // convert the max price impact to the min negative value\n // e.g. if sizeDeltaUsd is 10,000 and maxPriceImpactFactor is 2%\n // then minPriceImpactUsd = -200\n int256 minPriceImpactUsd = -Precision.applyFactor(params.order.sizeDeltaUsd(), maxPriceImpactFactor).toInt256();\n\n // cap totalImpactUsd to the min negative value and store the difference in priceImpactDiffUsd\n // e.g. if totalImpactUsd is -500 and minPriceImpactUsd is -200\n // then set priceImpactDiffUsd to -200 - -500 = 300\n // set totalImpactUsd to -200\n if (result.totalImpactUsd < minPriceImpactUsd) {\n result.priceImpactDiffUsd = (minPriceImpactUsd - result.totalImpactUsd).toUint256();\n result.totalImpactUsd = minPriceImpactUsd;\n }\n }\n\n result.totalImpactUsd = MarketUtils.capPositiveImpactUsdByMaxPositionImpact(\n params.contracts.dataStore,\n params.market.marketToken,\n result.totalImpactUsd,\n uint256(-sizeDeltaUsd)\n );\n\n // cap the positive totalImpactUsd by the available amount in the position impact pool\n result.totalImpactUsd = MarketUtils.capPositiveImpactUsdByPositionImpactPool(\n dataStore,\n market,\n prices,\n result.totalImpactUsd\n );\n }\n\n return result;\n }\n\n function getSwapPriceImpact(\n DataStore dataStore,\n Market.Props memory market,\n address tokenIn,\n address tokenOut,\n uint256 amountIn,\n Price.Props memory tokenInPrice,\n Price.Props memory tokenOutPrice\n ) external view returns (int256 priceImpactUsdBeforeCap, int256 priceImpactAmount, int256 tokenInPriceImpactAmount) {\n (priceImpactUsdBeforeCap, ) = SwapPricingUtils.getPriceImpactUsd(\n SwapPricingUtils.GetPriceImpactUsdParams(\n dataStore,\n market,\n tokenIn,\n tokenOut,\n tokenInPrice.midPrice(),\n tokenOutPrice.midPrice(),\n (amountIn * tokenInPrice.midPrice()).toInt256(),\n -(amountIn * tokenInPrice.midPrice()).toInt256(),\n true // includeVirtualInventoryImpact\n )\n );\n\n if (priceImpactUsdBeforeCap > 0) {\n uint256 cappedDiffUsd;\n (priceImpactAmount, cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap(\n dataStore,\n market.marketToken,\n tokenOut,\n tokenOutPrice,\n priceImpactUsdBeforeCap\n );\n\n if (cappedDiffUsd != 0) {\n (tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(\n dataStore,\n market.marketToken,\n tokenIn,\n tokenInPrice,\n cappedDiffUsd.toInt256()\n );\n }\n } else {\n (priceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(\n dataStore,\n market.marketToken,\n tokenIn,\n tokenInPrice,\n priceImpactUsdBeforeCap\n );\n }\n\n return (priceImpactUsdBeforeCap, priceImpactAmount, tokenInPriceImpactAmount);\n }\n\n function _getProportionalPendingImpactValues(\n uint256 sizeInUsd,\n int256 positionPendingImpactAmount,\n uint256 sizeDeltaUsd,\n Price.Props memory indexTokenPrice\n ) private pure returns (int256) {\n int256 proportionalPendingImpactAmount = Precision.mulDiv(positionPendingImpactAmount, sizeDeltaUsd, sizeInUsd, positionPendingImpactAmount < 0);\n\n // minimize the positive impact, maximize the negative impact\n int256 proportionalPendingImpactUsd = proportionalPendingImpactAmount > 0\n ? proportionalPendingImpactAmount * indexTokenPrice.min.toInt256()\n : proportionalPendingImpactAmount * indexTokenPrice.max.toInt256();\n\n return proportionalPendingImpactUsd;\n }\n}\n" + }, + "contracts/reader/ReaderUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\nimport \"../data/Keys.sol\";\n\nimport \"../market/MarketStoreUtils.sol\";\n\nimport \"../position/Position.sol\";\n\nimport \"../order/OrderStoreUtils.sol\";\n\nimport \"../adl/AdlUtils.sol\";\n\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\n\nimport \"./ReaderPositionUtils.sol\";\n\n// @title ReaderUtils\n// @dev Library for read utils functions\n// convers some internal library functions into external functions to reduce\n// the Reader contract size\nlibrary ReaderUtils {\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n using Price for Price.Props;\n using Position for Position.Props;\n using Order for Order.Props;\n\n struct VirtualInventory {\n uint256 virtualPoolAmountForLongToken;\n uint256 virtualPoolAmountForShortToken;\n int256 virtualInventoryForPositions;\n }\n\n struct MarketInfo {\n Market.Props market;\n uint256 borrowingFactorPerSecondForLongs;\n uint256 borrowingFactorPerSecondForShorts;\n BaseFundingValues baseFunding;\n MarketUtils.GetNextFundingAmountPerSizeResult nextFunding;\n VirtualInventory virtualInventory;\n bool isDisabled;\n }\n\n struct OrderInfo {\n bytes32 orderKey;\n Order.Props order;\n }\n\n struct BaseFundingValues {\n MarketUtils.PositionType fundingFeeAmountPerSize;\n MarketUtils.PositionType claimableFundingAmountPerSize;\n }\n\n function getOrder(DataStore dataStore, bytes32 key) external view returns (Order.Props memory) {\n return OrderStoreUtils.get(dataStore, key);\n }\n\n function getAccountOrders(\n DataStore dataStore,\n address account,\n uint256 start,\n uint256 end\n ) external view returns (OrderInfo[] memory) {\n bytes32[] memory orderKeys = OrderStoreUtils.getAccountOrderKeys(dataStore, account, start, end);\n OrderInfo[] memory orders = new OrderInfo[](orderKeys.length);\n for (uint256 i; i < orderKeys.length; i++) {\n bytes32 orderKey = orderKeys[i];\n orders[i] = OrderInfo(orderKey, OrderStoreUtils.get(dataStore, orderKey));\n }\n\n return orders;\n }\n\n function getBaseFundingValues(DataStore dataStore, Market.Props memory market) public view returns (BaseFundingValues memory) {\n BaseFundingValues memory values;\n\n values.fundingFeeAmountPerSize.long.longToken = MarketUtils.getFundingFeeAmountPerSize(\n dataStore,\n market.marketToken,\n market.longToken,\n true // isLong\n );\n\n values.fundingFeeAmountPerSize.long.shortToken = MarketUtils.getFundingFeeAmountPerSize(\n dataStore,\n market.marketToken,\n market.shortToken,\n true // isLong\n );\n\n values.fundingFeeAmountPerSize.short.longToken = MarketUtils.getFundingFeeAmountPerSize(\n dataStore,\n market.marketToken,\n market.longToken,\n false // isLong\n );\n\n values.fundingFeeAmountPerSize.short.shortToken = MarketUtils.getFundingFeeAmountPerSize(\n dataStore,\n market.marketToken,\n market.shortToken,\n false // isLong\n );\n\n values.claimableFundingAmountPerSize.long.longToken = MarketUtils.getClaimableFundingAmountPerSize(\n dataStore,\n market.marketToken,\n market.longToken,\n true // isLong\n );\n\n values.claimableFundingAmountPerSize.long.shortToken = MarketUtils.getClaimableFundingAmountPerSize(\n dataStore,\n market.marketToken,\n market.shortToken,\n true // isLong\n );\n\n values.claimableFundingAmountPerSize.short.longToken = MarketUtils.getClaimableFundingAmountPerSize(\n dataStore,\n market.marketToken,\n market.longToken,\n false // isLong\n );\n\n values.claimableFundingAmountPerSize.short.shortToken = MarketUtils.getClaimableFundingAmountPerSize(\n dataStore,\n market.marketToken,\n market.shortToken,\n false // isLong\n );\n\n return values;\n }\n\n function getMarkets(DataStore dataStore, uint256 start, uint256 end) external view returns (Market.Props[] memory) {\n address[] memory marketKeys = MarketStoreUtils.getMarketKeys(dataStore, start, end);\n Market.Props[] memory markets = new Market.Props[](marketKeys.length);\n for (uint256 i; i < marketKeys.length; i++) {\n address marketKey = marketKeys[i];\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);\n markets[i] = market;\n }\n\n return markets;\n }\n\n function getMarketInfo(\n DataStore dataStore,\n MarketUtils.MarketPrices memory prices,\n address marketKey\n ) public view returns (MarketInfo memory) {\n Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);\n\n uint256 borrowingFactorPerSecondForLongs = MarketUtils.getBorrowingFactorPerSecond(\n dataStore,\n market,\n prices,\n true\n );\n\n uint256 borrowingFactorPerSecondForShorts = MarketUtils.getBorrowingFactorPerSecond(\n dataStore,\n market,\n prices,\n false\n );\n\n BaseFundingValues memory baseFunding = getBaseFundingValues(dataStore, market);\n\n MarketUtils.GetNextFundingAmountPerSizeResult memory nextFunding = ReaderPositionUtils.getNextFundingAmountPerSize(\n dataStore,\n market,\n prices\n );\n\n VirtualInventory memory virtualInventory = getVirtualInventory(dataStore, market);\n\n bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));\n\n return\n MarketInfo(\n market,\n borrowingFactorPerSecondForLongs,\n borrowingFactorPerSecondForShorts,\n baseFunding,\n nextFunding,\n virtualInventory,\n isMarketDisabled\n );\n }\n\n function getMarketInfoList(\n DataStore dataStore,\n MarketUtils.MarketPrices[] memory marketPricesList,\n uint256 start,\n uint256 end\n ) external view returns (ReaderUtils.MarketInfo[] memory) {\n address[] memory marketKeys = MarketStoreUtils.getMarketKeys(dataStore, start, end);\n ReaderUtils.MarketInfo[] memory marketInfoList = new ReaderUtils.MarketInfo[](marketKeys.length);\n for (uint256 i; i < marketKeys.length; i++) {\n MarketUtils.MarketPrices memory prices = marketPricesList[i];\n address marketKey = marketKeys[i];\n marketInfoList[i] = getMarketInfo(dataStore, prices, marketKey);\n }\n\n return marketInfoList;\n }\n\n function getVirtualInventory(\n DataStore dataStore,\n Market.Props memory market\n ) internal view returns (VirtualInventory memory) {\n (, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils\n .getVirtualInventoryForSwaps(dataStore, market.marketToken);\n (, int256 virtualInventoryForPositions) = MarketUtils.getVirtualInventoryForPositions(\n dataStore,\n market.indexToken\n );\n\n return\n VirtualInventory(\n virtualPoolAmountForLongToken,\n virtualPoolAmountForShortToken,\n virtualInventoryForPositions\n );\n }\n\n function getAdlState(\n DataStore dataStore,\n address market,\n bool isLong,\n MarketUtils.MarketPrices memory prices\n ) external view returns (uint256, bool, int256, uint256) {\n uint256 latestAdlTime = AdlUtils.getLatestAdlTime(dataStore, market, isLong);\n Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market);\n\n (bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded(\n dataStore,\n _market,\n prices,\n isLong,\n Keys.MAX_PNL_FACTOR_FOR_ADL\n );\n\n return (latestAdlTime, shouldEnableAdl, pnlToPoolFactor, maxPnlFactor);\n }\n}\n" + }, + "contracts/reader/ReaderWithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\nimport \"../data/Keys.sol\";\n\nimport \"../position/Position.sol\";\nimport \"../market/MarketUtils.sol\";\nimport \"../market/Market.sol\";\n\nimport \"../pricing/ISwapPricingUtils.sol\";\nimport \"../pricing/SwapPricingUtils.sol\";\n\nlibrary ReaderWithdrawalUtils {\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n using Price for Price.Props;\n using Position for Position.Props;\n using Order for Order.Props;\n\n struct GetWithdrawalAmountOutCache {\n uint256 poolValue;\n uint256 marketTokensSupply;\n\n uint256 longTokenPoolAmount;\n uint256 shortTokenPoolAmount;\n\n uint256 longTokenPoolUsd;\n uint256 shortTokenPoolUsd;\n\n uint256 totalPoolUsd;\n\n uint256 marketTokensUsd;\n\n uint256 longTokenOutputUsd;\n uint256 shortTokenOutputUsd;\n\n uint256 longTokenOutputAmount;\n uint256 shortTokenOutputAmount;\n }\n\n function getWithdrawalAmountOut(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n uint256 marketTokenAmount,\n address uiFeeReceiver,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external view returns (uint256, uint256) {\n GetWithdrawalAmountOutCache memory cache;\n\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n dataStore,\n market,\n prices.indexTokenPrice,\n prices.longTokenPrice,\n prices.shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n false\n );\n\n if (poolValueInfo.poolValue <= 0) {\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\n }\n\n cache.poolValue = poolValueInfo.poolValue.toUint256();\n cache.marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));\n\n cache.longTokenPoolAmount = MarketUtils.getPoolAmount(dataStore, market, market.longToken);\n cache.shortTokenPoolAmount = MarketUtils.getPoolAmount(dataStore, market, market.shortToken);\n\n cache.longTokenPoolUsd = cache.longTokenPoolAmount * prices.longTokenPrice.max;\n cache.shortTokenPoolUsd = cache.shortTokenPoolAmount * prices.shortTokenPrice.max;\n\n cache.totalPoolUsd = cache.longTokenPoolUsd + cache.shortTokenPoolUsd;\n\n cache.marketTokensUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, cache.poolValue, cache.marketTokensSupply);\n\n cache.longTokenOutputUsd = Precision.mulDiv(cache.marketTokensUsd, cache.longTokenPoolUsd, cache.totalPoolUsd);\n cache.shortTokenOutputUsd = Precision.mulDiv(cache.marketTokensUsd, cache.shortTokenPoolUsd, cache.totalPoolUsd);\n\n cache.longTokenOutputAmount = cache.longTokenOutputUsd / prices.longTokenPrice.max;\n cache.shortTokenOutputAmount = cache.shortTokenOutputUsd / prices.shortTokenPrice.max;\n\n SwapPricingUtils.SwapFees memory longTokenFees = SwapPricingUtils.getSwapFees(\n dataStore,\n market.marketToken,\n cache.longTokenOutputAmount,\n false, // balanceWasImproved\n uiFeeReceiver,\n swapPricingType\n );\n\n SwapPricingUtils.SwapFees memory shortTokenFees = SwapPricingUtils.getSwapFees(\n dataStore,\n market.marketToken,\n cache.shortTokenOutputAmount,\n false, // balanceWasImproved\n uiFeeReceiver,\n swapPricingType\n );\n\n return (\n longTokenFees.amountAfterFees,\n shortTokenFees.amountAfterFees\n );\n }\n}\n" + }, + "contracts/referral/IReferralStorage.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title IReferralStorage\n// @dev Interface for ReferralStorage\ninterface IReferralStorage {\n // @dev get the owner of a referral code\n // @param _code the referral code\n // @return the owner of the referral code\n function codeOwners(bytes32 _code) external view returns (address);\n // @dev get the referral code of a trader\n // @param _account the address of the trader\n // @return the referral code\n function traderReferralCodes(address _account) external view returns (bytes32);\n // @dev get the trader discount share for an affiliate\n // @param _account the address of the affiliate\n // @return the trader discount share\n function referrerDiscountShares(address _account) external view returns (uint256);\n // @dev get the tier level of an affiliate\n // @param _account the address of the affiliate\n // @return the tier level of the affiliate\n function referrerTiers(address _account) external view returns (uint256);\n // @dev get the referral info for a trader\n // @param _account the address of the trader\n // @return (referral code, affiliate)\n function getTraderReferralInfo(address _account) external view returns (bytes32, address);\n // @dev set the referral code for a trader\n // @param _account the address of the trader\n // @param _code the referral code\n function setTraderReferralCode(address _account, bytes32 _code) external;\n // @dev set the values for a tier\n // @param _tierId the tier level\n // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)\n // @param _discountShare the share of the totalRebate for traders\n function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;\n // @dev set the tier for an affiliate\n // @param _tierId the tier level\n function setReferrerTier(address _referrer, uint256 _tierId) external;\n // @dev set the owner for a referral code\n // @param _code the referral code\n // @param _newAccount the new owner\n function govSetCodeOwner(bytes32 _code, address _newAccount) external;\n\n // @dev get the tier values for a tier level\n // @param _tierLevel the tier level\n // @return (totalRebate, discountShare)\n function tiers(uint256 _tierLevel) external view returns (uint256, uint256);\n}\n" + }, + "contracts/referral/ReferralEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nlibrary ReferralEventUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitAffiliateRewardUpdated(\n EventEmitter eventEmitter,\n address market,\n address token,\n address affiliate,\n uint256 delta,\n uint256 nextValue,\n uint256 nextPoolValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(3);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"affiliate\", affiliate);\n\n eventData.uintItems.initItems(3);\n eventData.uintItems.setItem(0, \"delta\", delta);\n eventData.uintItems.setItem(1, \"nextValue\", nextValue);\n eventData.uintItems.setItem(2, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog2(\n \"AffiliateRewardUpdated\",\n Cast.toBytes32(market),\n Cast.toBytes32(affiliate),\n eventData\n );\n }\n\n function emitAffiliateRewardClaimed(\n EventEmitter eventEmitter,\n address market,\n address token,\n address affiliate,\n address receiver,\n uint256 amount,\n uint256 nextPoolValue\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(4);\n eventData.addressItems.setItem(0, \"market\", market);\n eventData.addressItems.setItem(1, \"token\", token);\n eventData.addressItems.setItem(2, \"affiliate\", affiliate);\n eventData.addressItems.setItem(3, \"receiver\", receiver);\n\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"amount\", amount);\n eventData.uintItems.setItem(1, \"nextPoolValue\", nextPoolValue);\n\n eventEmitter.emitEventLog1(\n \"AffiliateRewardClaimed\",\n Cast.toBytes32(affiliate),\n eventData\n );\n }\n}\n" + }, + "contracts/referral/ReferralTier.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// @title ReferralTier\n// @dev Struct for referral tiers\nlibrary ReferralTier {\n // @param totalRebate the total rebate for the tier (affiliate reward + trader discount)\n // @param discountShare the share of the totalRebate for traders\n struct Props {\n uint256 totalRebate;\n uint256 discountShare;\n }\n}\n" + }, + "contracts/referral/ReferralUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\n\nimport \"../event/EventEmitter.sol\";\nimport \"../market/MarketToken.sol\";\nimport \"../market/MarketUtils.sol\";\n\nimport \"./IReferralStorage.sol\";\nimport \"./ReferralEventUtils.sol\";\n\nimport \"../utils/Precision.sol\";\n\n// @title ReferralUtils\n// @dev Library for referral functions\nlibrary ReferralUtils {\n // @dev set the referral code for a trader\n // @param referralStorage The referral storage instance to use.\n // @param account The account of the trader.\n // @param referralCode The referral code.\n function setTraderReferralCode(\n IReferralStorage referralStorage,\n address account,\n bytes32 referralCode\n ) internal {\n if (referralCode == bytes32(0)) { return; }\n if (address(referralStorage) == address(0)) { return; }\n\n // skip setting of the referral code if the user already has a referral code\n if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }\n\n referralStorage.setTraderReferralCode(account, referralCode);\n }\n\n // @dev Increments the affiliate's reward balance by the specified delta.\n // @param dataStore The data store instance to use.\n // @param eventEmitter The event emitter instance to use.\n // @param market The market address.\n // @param token The token address.\n // @param affiliate The affiliate's address.\n // @param trader The trader's address.\n // @param delta The amount to increment the reward balance by.\n function incrementAffiliateReward(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n address affiliate,\n uint256 delta\n ) internal {\n if (delta == 0) { return; }\n\n uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);\n uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);\n\n ReferralEventUtils.emitAffiliateRewardUpdated(\n eventEmitter,\n market,\n token,\n affiliate,\n delta,\n nextValue,\n nextPoolValue\n );\n }\n\n // @dev Gets the referral information for the specified trader.\n // @param referralStorage The referral storage instance to use.\n // @param trader The trader's address.\n // @return The affiliate's address, the total rebate, and the discount share.\n function getReferralInfo(\n DataStore dataStore,\n IReferralStorage referralStorage,\n address trader\n ) internal view returns (bytes32, address, uint256, uint256, uint256) {\n if (address(referralStorage) == address(0)) {\n return (bytes32(0), address(0), 0, 0, 0);\n }\n\n bytes32 code = referralStorage.traderReferralCodes(trader);\n address affiliate;\n uint256 totalRebate;\n uint256 discountShare;\n uint256 minAffiliateRewardFactor;\n\n if (code != bytes32(0)) {\n affiliate = referralStorage.codeOwners(code);\n uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);\n (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);\n minAffiliateRewardFactor = dataStore.getUint(Keys.minAffiliateRewardFactorKey(referralTierLevel));\n\n uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);\n if (customDiscountShare != 0) {\n discountShare = customDiscountShare;\n }\n }\n\n uint256 traderDiscountFactor = Precision.basisPointsToFloat(totalRebate * discountShare / Precision.BASIS_POINTS_DIVISOR);\n uint256 totalRebateFactor = Precision.basisPointsToFloat(totalRebate);\n uint256 affiliateRewardFactor = totalRebateFactor - traderDiscountFactor;\n\n return (\n code,\n affiliate,\n affiliateRewardFactor,\n traderDiscountFactor,\n minAffiliateRewardFactor\n );\n }\n\n // @dev Claims affiliate rewards for the given markets and tokens and sends the rewards to the specified receiver.\n // @param dataStore The data store instance to use.\n // @param eventEmitter The event emitter instance to use.\n // @param markets An array of market addresses\n // @param tokens An array of token addresses, corresponding to the given markets\n // @param receiver The address to which the claimed rewards should be sent\n // @param account The affiliate's address.\n function batchClaimAffiliateRewards(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address[] memory markets,\n address[] memory tokens,\n address receiver,\n address account\n ) external returns (uint256[] memory) {\n if (markets.length != tokens.length) {\n revert Errors.InvalidClaimAffiliateRewardsInput(markets.length, tokens.length);\n }\n\n FeatureUtils.validateFeature(dataStore, Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)));\n\n AccountUtils.validateReceiver(receiver);\n\n uint256[] memory claimedAmounts = new uint256[](markets.length);\n\n for (uint256 i; i < markets.length; i++) {\n claimedAmounts[i] = _claimAffiliateReward(\n dataStore,\n eventEmitter,\n markets[i],\n tokens[i],\n account,\n receiver\n );\n }\n\n return claimedAmounts;\n }\n\n function _claimAffiliateReward(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address market,\n address token,\n address account,\n address receiver\n ) private returns (uint256) {\n bytes32 key = Keys.affiliateRewardKey(market, token, account);\n\n uint256 rewardAmount = dataStore.getUint(key);\n dataStore.setUint(key, 0);\n\n uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);\n\n MarketToken(payable(market)).transferOut(\n token,\n receiver,\n rewardAmount\n );\n\n MarketUtils.validateMarketTokenBalance(dataStore, market);\n\n ReferralEventUtils.emitAffiliateRewardClaimed(\n eventEmitter,\n market,\n token,\n account,\n receiver,\n rewardAmount,\n nextPoolValue\n );\n\n return rewardAmount;\n }\n}\n" + }, + "contracts/role/Role.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n/**\n * @title Role\n * @dev Library for role keys\n */\nlibrary Role {\n /**\n * @dev The ROLE_ADMIN role.\n * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9\n */\n bytes32 public constant ROLE_ADMIN = keccak256(abi.encode(\"ROLE_ADMIN\"));\n\n /**\n * @dev The TIMELOCK_ADMIN role.\n * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c\n */\n bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode(\"TIMELOCK_ADMIN\"));\n\n /**\n * @dev The TIMELOCK_MULTISIG role.\n * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a\n */\n bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode(\"TIMELOCK_MULTISIG\"));\n\n /**\n * @dev The CONFIG_KEEPER role.\n * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b\n */\n bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode(\"CONFIG_KEEPER\"));\n\n /**\n * @dev The LIMITED_CONFIG_KEEPER role.\n * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7\n */\n bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode(\"LIMITED_CONFIG_KEEPER\"));\n\n /**\n * @dev The CONTROLLER role.\n * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b\n */\n bytes32 public constant CONTROLLER = keccak256(abi.encode(\"CONTROLLER\"));\n\n /**\n * @dev The GOV_TOKEN_CONTROLLER role.\n * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690\n */\n bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode(\"GOV_TOKEN_CONTROLLER\"));\n\n /**\n * @dev The ROUTER_PLUGIN role.\n * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3\n */\n bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode(\"ROUTER_PLUGIN\"));\n\n /**\n * @dev The MARKET_KEEPER role.\n * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae\n */\n bytes32 public constant MARKET_KEEPER = keccak256(abi.encode(\"MARKET_KEEPER\"));\n\n /**\n * @dev The FEE_KEEPER role.\n * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8\n */\n bytes32 public constant FEE_KEEPER = keccak256(abi.encode(\"FEE_KEEPER\"));\n\n /**\n * @dev The FEE_DISTRIBUTION_KEEPER role.\n * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2\n */\n bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode(\"FEE_DISTRIBUTION_KEEPER\"));\n\n /**\n * @dev The ORDER_KEEPER role.\n * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794\n */\n bytes32 public constant ORDER_KEEPER = keccak256(abi.encode(\"ORDER_KEEPER\"));\n\n /**\n * @dev The FROZEN_ORDER_KEEPER role.\n * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07\n */\n bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode(\"FROZEN_ORDER_KEEPER\"));\n\n /**\n * @dev The PRICING_KEEPER role.\n * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103\n */\n bytes32 public constant PRICING_KEEPER = keccak256(abi.encode(\"PRICING_KEEPER\"));\n /**\n * @dev The LIQUIDATION_KEEPER role.\n * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e\n */\n bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode(\"LIQUIDATION_KEEPER\"));\n /**\n * @dev The ADL_KEEPER role.\n * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91\n */\n bytes32 public constant ADL_KEEPER = keccak256(abi.encode(\"ADL_KEEPER\"));\n /**\n * @dev The CONTRIBUTOR_KEEPER role.\n * Hash: 0xfa89e7b5ea0a346d73c71d7d6a3512b9f2ea2c2e6c5fb8211ec351d35deef0f4\n */\n bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode(\"CONTRIBUTOR_KEEPER\"));\n /**\n * @dev The CONTRIBUTOR_DISTRIBUTOR role.\n * Hash: 0xcdf6da7ad30d8b9afea66fb1cb11b1b7d0b50e9b30b69561a3ca52c39251360c\n */\n bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode(\"CONTRIBUTOR_DISTRIBUTOR\"));\n\n /**\n * @dev The CLAIM_ADMIN role.\n * Hash: 0x3816efacf145d41a12de1ee8ae9dc340b887f4ca0f3bba62a645b2fefa4cab33\n */\n bytes32 public constant CLAIM_ADMIN = keccak256(abi.encode(\"CLAIM_ADMIN\"));\n /**\n * @dev The MULTICHAIN_READER role.\n * Hash: 0xdb34a94d601aa170c498f99c1628bd6182669f4ea4522eb87795649193ee93f8\n */\n bytes32 public constant MULTICHAIN_READER = keccak256(abi.encode(\"MULTICHAIN_READER\"));\n}\n" + }, + "contracts/role/RoleModule.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./RoleStore.sol\";\n\n/**\n * @title RoleModule\n * @dev Contract for role validation functions\n */\ncontract RoleModule {\n RoleStore public immutable roleStore;\n\n /**\n * @dev Constructor that initializes the role store for this contract.\n *\n * @param _roleStore The contract instance to use as the role store.\n */\n constructor(RoleStore _roleStore) {\n roleStore = _roleStore;\n }\n\n /**\n * @dev Only allows the contract's own address to call the function.\n */\n modifier onlySelf() {\n if (msg.sender != address(this)) {\n revert Errors.Unauthorized(msg.sender, \"SELF\");\n }\n _;\n }\n\n /**\n * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.\n */\n modifier onlyTimelockMultisig() {\n _validateRole(Role.TIMELOCK_MULTISIG, \"TIMELOCK_MULTISIG\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.\n */\n modifier onlyTimelockAdmin() {\n _validateRole(Role.TIMELOCK_ADMIN, \"TIMELOCK_ADMIN\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.\n */\n modifier onlyConfigKeeper() {\n _validateRole(Role.CONFIG_KEEPER, \"CONFIG_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the LIMITED_CONFIG_KEEPER role to call the function.\n */\n modifier onlyLimitedConfigKeeper() {\n _validateRole(Role.LIMITED_CONFIG_KEEPER, \"LIMITED_CONFIG_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the CONTROLLER role to call the function.\n */\n modifier onlyController() {\n _validateRole(Role.CONTROLLER, \"CONTROLLER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.\n */\n modifier onlyGovTokenController() {\n _validateRole(Role.GOV_TOKEN_CONTROLLER, \"GOV_TOKEN_CONTROLLER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.\n */\n modifier onlyRouterPlugin() {\n _validateRole(Role.ROUTER_PLUGIN, \"ROUTER_PLUGIN\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the MARKET_KEEPER role to call the function.\n */\n modifier onlyMarketKeeper() {\n _validateRole(Role.MARKET_KEEPER, \"MARKET_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the FEE_KEEPER role to call the function.\n */\n modifier onlyFeeKeeper() {\n _validateRole(Role.FEE_KEEPER, \"FEE_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.\n */\n modifier onlyFeeDistributionKeeper() {\n _validateRole(Role.FEE_DISTRIBUTION_KEEPER, \"FEE_DISTRIBUTION_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the ORDER_KEEPER role to call the function.\n */\n modifier onlyOrderKeeper() {\n _validateRole(Role.ORDER_KEEPER, \"ORDER_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the PRICING_KEEPER role to call the function.\n */\n modifier onlyPricingKeeper() {\n _validateRole(Role.PRICING_KEEPER, \"PRICING_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.\n */\n modifier onlyLiquidationKeeper() {\n _validateRole(Role.LIQUIDATION_KEEPER, \"LIQUIDATION_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the ADL_KEEPER role to call the function.\n */\n modifier onlyAdlKeeper() {\n _validateRole(Role.ADL_KEEPER, \"ADL_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the CONTRIBUTOR_KEEPER role to call the function.\n */\n modifier onlyContributorKeeper() {\n _validateRole(Role.CONTRIBUTOR_KEEPER, \"CONTRIBUTOR_KEEPER\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\n */\n modifier onlyContributorDistributor() {\n _validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, \"CONTRIBUTOR_DISTRIBUTOR\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the CLAIM_ADMIN role to call the function.\n */\n modifier onlyClaimAdmin() {\n _validateRole(Role.CLAIM_ADMIN, \"CLAIM_ADMIN\");\n _;\n }\n\n /**\n * @dev Only allows addresses with the CONTRIBUTOR_DISTRIBUTOR role to call the function.\n */\n modifier onlyMultichainReader() {\n _validateRole(Role.MULTICHAIN_READER, \"MULTICHAIN_READER\");\n _;\n }\n\n /**\n * @dev Validates that the caller has the specified role.\n *\n * If the caller does not have the specified role, the transaction is reverted.\n *\n * @param role The key of the role to validate.\n * @param roleName The name of the role to validate.\n */\n function _validateRole(bytes32 role, string memory roleName) internal view {\n if (!roleStore.hasRole(msg.sender, role)) {\n revert Errors.Unauthorized(msg.sender, roleName);\n }\n }\n}\n" + }, + "contracts/role/RoleStore.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"../utils/EnumerableValues.sol\";\nimport \"./Role.sol\";\nimport \"../error/Errors.sol\";\n\n/**\n * @title RoleStore\n * @dev Stores roles and their members.\n */\ncontract RoleStore {\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableSet for EnumerableSet.Bytes32Set;\n using EnumerableValues for EnumerableSet.AddressSet;\n using EnumerableValues for EnumerableSet.Bytes32Set;\n\n EnumerableSet.Bytes32Set internal roles;\n mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;\n // checking if an account has a role is a frequently used function\n // roleCache helps to save gas by offering a more efficient lookup\n // vs calling roleMembers[key].contains(account)\n mapping(address => mapping (bytes32 => bool)) roleCache;\n\n modifier onlyRoleAdmin() {\n if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {\n revert Errors.Unauthorized(msg.sender, \"ROLE_ADMIN\");\n }\n _;\n }\n\n constructor() {\n _grantRole(msg.sender, Role.ROLE_ADMIN);\n }\n\n /**\n * @dev Grants the specified role to the given account.\n *\n * @param account The address of the account.\n * @param roleKey The key of the role to grant.\n */\n function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {\n _grantRole(account, roleKey);\n }\n\n /**\n * @dev Revokes the specified role from the given account.\n *\n * @param account The address of the account.\n * @param roleKey The key of the role to revoke.\n */\n function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {\n _revokeRole(account, roleKey);\n }\n\n /**\n * @dev Returns true if the given account has the specified role.\n *\n * @param account The address of the account.\n * @param roleKey The key of the role.\n * @return True if the account has the role, false otherwise.\n */\n function hasRole(address account, bytes32 roleKey) public view returns (bool) {\n return roleCache[account][roleKey];\n }\n\n /**\n * @dev Returns the number of roles stored in the contract.\n *\n * @return The number of roles.\n */\n function getRoleCount() external view returns (uint256) {\n return roles.length();\n }\n\n /**\n * @dev Returns the keys of the roles stored in the contract.\n *\n * @param start The starting index of the range of roles to return.\n * @param end The ending index of the range of roles to return.\n * @return The keys of the roles.\n */\n function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {\n return roles.valuesAt(start, end);\n }\n\n /**\n * @dev Returns the number of members of the specified role.\n *\n * @param roleKey The key of the role.\n * @return The number of members of the role.\n */\n function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {\n return roleMembers[roleKey].length();\n }\n\n /**\n * @dev Returns the members of the specified role.\n *\n * @param roleKey The key of the role.\n * @param start the start index, the value for this index will be included.\n * @param end the end index, the value for this index will not be included.\n * @return The members of the role.\n */\n function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {\n return roleMembers[roleKey].valuesAt(start, end);\n }\n\n function _grantRole(address account, bytes32 roleKey) internal {\n roles.add(roleKey);\n roleMembers[roleKey].add(account);\n roleCache[account][roleKey] = true;\n }\n\n function _revokeRole(address account, bytes32 roleKey) internal {\n roleMembers[roleKey].remove(account);\n roleCache[account][roleKey] = false;\n\n if (roleMembers[roleKey].length() == 0) {\n if (roleKey == Role.ROLE_ADMIN) {\n revert Errors.ThereMustBeAtLeastOneRoleAdmin();\n }\n if (roleKey == Role.TIMELOCK_MULTISIG) {\n revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();\n }\n }\n }\n}\n" + }, + "contracts/router/BaseRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../utils/PayableMulticall.sol\";\nimport \"../utils/AccountUtils.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../token/TokenUtils.sol\";\n\nimport \"./Router.sol\";\n\ncontract BaseRouter is ReentrancyGuard, PayableMulticall, RoleModule {\n using SafeERC20 for IERC20;\n\n Router public immutable router;\n DataStore public immutable dataStore;\n EventEmitter public immutable eventEmitter;\n\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter\n ) RoleModule(_roleStore) {\n router = _router;\n dataStore = _dataStore;\n eventEmitter = _eventEmitter;\n }\n\n // @dev Wraps the specified amount of native tokens into WNT then sends the WNT to the specified address\n function sendWnt(address receiver, uint256 amount) external payable nonReentrant {\n AccountUtils.validateReceiver(receiver);\n TokenUtils.depositAndSendWrappedNativeToken(dataStore, receiver, amount);\n }\n\n // @dev Sends the given amount of tokens to the given address\n function sendTokens(address token, address receiver, uint256 amount) external payable nonReentrant {\n AccountUtils.validateReceiver(receiver);\n address account = msg.sender;\n router.pluginTransfer(token, account, receiver, amount);\n }\n\n function sendNativeToken(address receiver, uint256 amount) external payable nonReentrant {\n AccountUtils.validateReceiver(receiver);\n TokenUtils.sendNativeToken(dataStore, receiver, amount);\n }\n}\n" + }, + "contracts/router/ExchangeRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../exchange/IDepositHandler.sol\";\nimport \"../exchange/IWithdrawalHandler.sol\";\nimport \"../exchange/IShiftHandler.sol\";\nimport \"../exchange/IOrderHandler.sol\";\nimport \"../external/IExternalHandler.sol\";\n\nimport \"../deposit/DepositStoreUtils.sol\";\nimport \"../withdrawal/WithdrawalStoreUtils.sol\";\nimport \"../shift/IShiftUtils.sol\";\nimport \"../shift/ShiftStoreUtils.sol\";\nimport \"../order/OrderStoreUtils.sol\";\n\nimport \"../callback/CallbackUtils.sol\";\nimport \"../fee/FeeUtils.sol\";\nimport \"../nonce/NonceUtils.sol\";\nimport \"../referral/ReferralUtils.sol\";\n\nimport \"./BaseRouter.sol\";\nimport \"./IExchangeRouter.sol\";\n\n/**\n * @title ExchangeRouter\n * @dev Router for exchange functions, supports functions which require\n * token transfers from the user\n *\n * IMPORTANT: PayableMulticall uses delegatecall, msg.value will be the same for each delegatecall\n * extra care should be taken when using msg.value in any of the functions in this contract\n *\n * To avoid front-running issues, most actions require two steps to execute:\n *\n * - User sends transaction with request details, e.g. deposit / withdraw liquidity,\n * swap, increase / decrease position\n * - Keepers listen for the transactions, include the prices for the request then\n * send a transaction to execute the request\n *\n * Prices are provided by an off-chain oracle system:\n *\n * - Oracle keepers continually check the latest blocks\n * - When there is a new block, oracle keepers fetch the latest prices from\n * reference exchanges\n * - Oracle keepers then sign the median price for each token together with\n * the block hash\n * - Oracle keepers then send the data and signature to archive nodes\n * - Archive nodes display this information for anyone to query\n *\n * Example:\n *\n * - Block 100 is finalized on the blockchain\n * - Oracle keepers observe this block\n * - Oracle keepers pull the latest prices from reference exchanges,\n * token A: price 20,000, token B: price 80,000\n * - Oracle keepers sign [chainId, blockhash(100), 20,000], [chainId, blockhash(100), 80,000]\n * - If in block 100, there was a market order to open a long position for token A,\n * the market order would have a block number of 100\n * - The prices signed at block 100 can be used to execute this order\n * - Order keepers would bundle the signature and price data for token A\n * then execute the order\n */\ncontract ExchangeRouter is IExchangeRouter, BaseRouter {\n using Deposit for Deposit.Props;\n using Withdrawal for Withdrawal.Props;\n using Order for Order.Props;\n using Shift for Shift.Props;\n\n IDepositHandler public immutable depositHandler;\n IWithdrawalHandler public immutable withdrawalHandler;\n IShiftHandler public immutable shiftHandler;\n IOrderHandler public immutable orderHandler;\n IExternalHandler public immutable externalHandler;\n\n // @dev Constructor that initializes the contract with the provided Router, RoleStore, DataStore,\n // EventEmitter, IDepositHandler, IWithdrawalHandler, IOrderHandler, and OrderStore instances\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IDepositHandler _depositHandler,\n IWithdrawalHandler _withdrawalHandler,\n IShiftHandler _shiftHandler,\n IOrderHandler _orderHandler,\n IExternalHandler _externalHandler\n ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) {\n depositHandler = _depositHandler;\n withdrawalHandler = _withdrawalHandler;\n shiftHandler = _shiftHandler;\n orderHandler = _orderHandler;\n externalHandler = _externalHandler;\n }\n\n // makeExternalCalls can be used to perform an external swap before\n // an action\n // example:\n // - ExchangeRouter.sendTokens(token: WETH, receiver: externalHandler, amount: 1e18)\n // - ExchangeRouter.makeExternalCalls(\n // WETH.approve(spender: aggregator, amount: 1e18),\n // aggregator.swap(amount: 1, from: WETH, to: USDC, receiver: orderHandler)\n // )\n // - ExchangeRouter.createOrder\n // the msg.sender for makeExternalCalls would be externalHandler\n // refundTokens can be used to retrieve any excess tokens that may\n // be left in the externalHandler\n function makeExternalCalls(\n address[] memory externalCallTargets,\n bytes[] memory externalCallDataList,\n address[] memory refundTokens,\n address[] memory refundReceivers\n ) external payable nonReentrant {\n externalHandler.makeExternalCalls(\n externalCallTargets,\n externalCallDataList,\n refundTokens,\n refundReceivers\n );\n }\n\n /**\n * @dev Creates a new deposit with the given long token, short token, long token amount, short token\n * amount, and deposit parameters. The deposit is created by transferring the specified amounts of\n * long and short tokens from the caller's account to the deposit store, and then calling the\n * `createDeposit()` function on the deposit handler contract.\n *\n * @param params The deposit parameters, as specified in the `IDepositUtils.CreateDepositParams` struct\n * @return The unique ID of the newly created deposit\n */\n function createDeposit(\n IDepositUtils.CreateDepositParams calldata params\n ) external override payable nonReentrant returns (bytes32) {\n address account = msg.sender;\n\n return depositHandler.createDeposit(\n account,\n 0, // srcChainId is the current block.chainId\n params\n );\n }\n\n function cancelDeposit(bytes32 key) external override payable nonReentrant {\n Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);\n if (deposit.account() == address(0)) {\n revert Errors.EmptyDeposit();\n }\n\n if (deposit.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for cancelDeposit\");\n }\n\n depositHandler.cancelDeposit(key);\n }\n\n function simulateExecuteDeposit(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n depositHandler.simulateExecuteDeposit(key, simulatedOracleParams);\n }\n\n function simulateExecuteLatestDeposit(\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n bytes32 key = NonceUtils.getCurrentKey(dataStore);\n depositHandler.simulateExecuteDeposit(key, simulatedOracleParams);\n }\n\n function createWithdrawal(\n IWithdrawalUtils.CreateWithdrawalParams calldata params\n ) external override payable nonReentrant returns (bytes32) {\n address account = msg.sender;\n\n return withdrawalHandler.createWithdrawal(\n account,\n 0, // srcChainId is the current block.chainId\n params\n );\n }\n\n function cancelWithdrawal(bytes32 key) external override payable nonReentrant {\n Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);\n if (withdrawal.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for cancelWithdrawal\");\n }\n\n withdrawalHandler.cancelWithdrawal(key);\n }\n\n function executeAtomicWithdrawal(\n IWithdrawalUtils.CreateWithdrawalParams calldata params,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external override payable nonReentrant {\n address account = msg.sender;\n\n return withdrawalHandler.executeAtomicWithdrawal(\n account,\n params,\n oracleParams\n );\n }\n\n function simulateExecuteWithdrawal(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory simulatedOracleParams,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external payable nonReentrant {\n withdrawalHandler.simulateExecuteWithdrawal(key, simulatedOracleParams, swapPricingType);\n }\n\n function simulateExecuteLatestWithdrawal(\n OracleUtils.SimulatePricesParams memory simulatedOracleParams,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external payable nonReentrant {\n bytes32 key = NonceUtils.getCurrentKey(dataStore);\n withdrawalHandler.simulateExecuteWithdrawal(key, simulatedOracleParams, swapPricingType);\n }\n\n function createShift(\n IShiftUtils.CreateShiftParams calldata params\n ) external override payable nonReentrant returns (bytes32) {\n address account = msg.sender;\n\n return shiftHandler.createShift(\n account,\n 0, // srcChainId is the current block.chainId\n params\n );\n }\n\n function cancelShift(bytes32 key) external override payable nonReentrant {\n Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);\n if (shift.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for cancelShift\");\n }\n\n shiftHandler.cancelShift(key);\n }\n\n function simulateExecuteShift(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n shiftHandler.simulateExecuteShift(key, simulatedOracleParams);\n }\n\n function simulateExecuteLatestShift(\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n bytes32 key = NonceUtils.getCurrentKey(dataStore);\n shiftHandler.simulateExecuteShift(key, simulatedOracleParams);\n }\n\n /**\n * @dev Creates a new order with the given amount, order parameters. The order is\n * created by transferring the specified amount of collateral tokens from the caller's account to the\n * order store, and then calling the `createOrder()` function on the order handler contract. The\n * referral code is also set on the caller's account using the referral storage contract.\n */\n function createOrder(\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external override payable nonReentrant returns (bytes32) {\n address account = msg.sender;\n\n return orderHandler.createOrder(\n account,\n 0, // srcChainId is the current block.chainId\n params,\n false\n );\n }\n\n function setSavedCallbackContract(\n address market,\n address callbackContract\n ) external payable nonReentrant {\n // save the callback contract based on the account and market so that\n // it can be called on liquidations and ADLs\n CallbackUtils.setSavedCallbackContract(\n dataStore,\n msg.sender, // account\n market,\n callbackContract\n );\n }\n\n /**\n * @dev Updates the given order with the specified size delta, acceptable price, and trigger price.\n * The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner\n * of the order, and the order must not be a market order. The size delta, trigger price, and\n * acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is\n * transferred to the contract is added to the order's execution fee. The updated order is then saved\n * in the order store, and an `OrderUpdated` event is emitted.\n *\n * @param key The unique ID of the order to be updated\n * @param sizeDeltaUsd The new size delta for the order\n * @param acceptablePrice The new acceptable price for the order\n * @param triggerPrice The new trigger price for the order\n */\n function updateOrder(\n bytes32 key,\n uint256 sizeDeltaUsd,\n uint256 acceptablePrice,\n uint256 triggerPrice,\n uint256 minOutputAmount,\n uint256 validFromTime,\n bool autoCancel\n ) external payable nonReentrant {\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n if (order.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for updateOrder\");\n }\n\n orderHandler.updateOrder(\n key,\n sizeDeltaUsd,\n acceptablePrice,\n triggerPrice,\n minOutputAmount,\n validFromTime,\n autoCancel,\n order,\n false\n );\n }\n\n /**\n * @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order\n * type. The caller must be the owner of the order, and the order must not be a market order. The\n * order is cancelled by calling the `cancelOrder()` function in the `OrderUtils` contract. This\n * function also records the starting gas amount and the reason for cancellation, which is passed to\n * the `cancelOrder()` function.\n *\n * @param key The unique ID of the order to be cancelled\n */\n function cancelOrder(bytes32 key) external payable nonReentrant {\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n if (order.account() == address(0)) {\n revert Errors.EmptyOrder();\n }\n\n if (order.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for cancelOrder\");\n }\n\n orderHandler.cancelOrder(key);\n }\n\n function simulateExecuteOrder(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n orderHandler.simulateExecuteOrder(key, simulatedOracleParams);\n }\n\n function simulateExecuteLatestOrder(\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n bytes32 key = NonceUtils.getCurrentKey(dataStore);\n orderHandler.simulateExecuteOrder(key, simulatedOracleParams);\n }\n\n /**\n * @dev Claims funding fees for the given markets and tokens on behalf of the caller, and sends the\n * fees to the specified receiver. The length of the `markets` and `tokens` arrays must be the same.\n * For each market-token pair, the `claimFundingFees()` function in the `MarketUtils` contract is\n * called to claim the fees for the caller.\n *\n * @param markets An array of market addresses\n * @param tokens An array of token addresses, corresponding to the given markets\n * @param receiver The address to which the claimed fees should be sent\n */\n function claimFundingFees(\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external payable nonReentrant returns (uint256[] memory) {\n address account = msg.sender;\n return\n FeeUtils.batchClaimFundingFees(\n dataStore,\n eventEmitter,\n markets,\n tokens,\n receiver,\n account\n );\n }\n\n function claimCollateral(\n address[] memory markets,\n address[] memory tokens,\n uint256[] memory timeKeys,\n address receiver\n ) external payable nonReentrant returns (uint256[] memory) {\n address account = msg.sender;\n return\n MarketUtils.batchClaimCollateral(\n dataStore,\n eventEmitter,\n markets,\n tokens,\n timeKeys,\n receiver,\n account\n );\n }\n\n /**\n * @dev Claims affiliate rewards for the given markets and tokens on behalf of the caller, and sends\n * the rewards to the specified receiver. The length of the `markets` and `tokens` arrays must be\n * the same. For each market-token pair, the `claimAffiliateReward()` function in the `ReferralUtils`\n * contract is called to claim the rewards for the caller.\n *\n * @param markets An array of market addresses\n * @param tokens An array of token addresses, corresponding to the given markets\n * @param receiver The address to which the claimed rewards should be sent\n */\n function claimAffiliateRewards(\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external payable nonReentrant returns (uint256[] memory) {\n address account = msg.sender;\n return\n ReferralUtils.batchClaimAffiliateRewards(\n dataStore,\n eventEmitter,\n markets,\n tokens,\n receiver,\n account\n );\n }\n\n function setUiFeeFactor(uint256 uiFeeFactor) external payable nonReentrant {\n address account = msg.sender;\n MarketUtils.setUiFeeFactor(dataStore, eventEmitter, account, uiFeeFactor);\n }\n\n function claimUiFees(\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external payable nonReentrant returns (uint256[] memory) {\n address uiFeeReceiver = msg.sender;\n return FeeUtils.batchClaimUiFees(dataStore, eventEmitter, markets, tokens, receiver, uiFeeReceiver);\n }\n}\n" + }, + "contracts/router/GlvRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseRouter.sol\";\nimport \"../exchange/IGlvWithdrawalHandler.sol\";\nimport \"../exchange/IGlvDepositHandler.sol\";\nimport \"../external/IExternalHandler.sol\";\nimport \"../glv/glvDeposit/GlvDepositStoreUtils.sol\";\nimport \"../glv/glvWithdrawal/GlvWithdrawalStoreUtils.sol\";\nimport \"../nonce/NonceUtils.sol\";\n\ncontract GlvRouter is BaseRouter {\n using GlvDeposit for GlvDeposit.Props;\n using GlvWithdrawal for GlvWithdrawal.Props;\n\n IGlvDepositHandler public immutable glvDepositHandler;\n IGlvWithdrawalHandler public immutable glvWithdrawalHandler;\n IExternalHandler public immutable externalHandler;\n\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IGlvDepositHandler _glvDepositHandler,\n IGlvWithdrawalHandler _glvWithdrawalHandler,\n IExternalHandler _externalHandler\n ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) {\n glvDepositHandler = _glvDepositHandler;\n glvWithdrawalHandler = _glvWithdrawalHandler;\n externalHandler = _externalHandler;\n }\n\n receive() external payable {\n address wnt = TokenUtils.wnt(dataStore);\n if (msg.sender != wnt) {\n revert Errors.InvalidNativeTokenSender(msg.sender);\n }\n }\n\n function createGlvDeposit(\n IGlvDepositUtils.CreateGlvDepositParams calldata params\n ) external payable nonReentrant returns (bytes32) {\n address account = msg.sender;\n\n return glvDepositHandler.createGlvDeposit(account, 0, params); // srcChainId is the current block.chainId\n }\n\n function cancelGlvDeposit(bytes32 key) external nonReentrant {\n GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(dataStore, key);\n if (glvDeposit.account() == address(0)) {\n revert Errors.EmptyGlvDeposit();\n }\n\n if (glvDeposit.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for cancelGlvDeposit\");\n }\n\n glvDepositHandler.cancelGlvDeposit(key);\n }\n\n function simulateExecuteGlvDeposit(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n glvDepositHandler.simulateExecuteGlvDeposit(key, simulatedOracleParams);\n }\n\n function simulateExecuteLatestGlvDeposit(\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n bytes32 key = NonceUtils.getCurrentKey(dataStore);\n glvDepositHandler.simulateExecuteGlvDeposit(key, simulatedOracleParams);\n }\n\n function createGlvWithdrawal(\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams calldata params\n ) external payable nonReentrant returns (bytes32) {\n address account = msg.sender;\n\n return glvWithdrawalHandler.createGlvWithdrawal(account, 0, params); // srcChainId is the current block.chainId\n }\n\n function cancelGlvWithdrawal(bytes32 key) external nonReentrant {\n GlvWithdrawal.Props memory glvWithdrawal = GlvWithdrawalStoreUtils.get(dataStore, key);\n if (glvWithdrawal.account() == address(0)) {\n revert Errors.EmptyGlvWithdrawal();\n }\n\n if (glvWithdrawal.account() != msg.sender) {\n revert Errors.Unauthorized(msg.sender, \"account for cancelGlvWithdrawal\");\n }\n\n glvWithdrawalHandler.cancelGlvWithdrawal(key);\n }\n\n function simulateExecuteGlvWithdrawal(\n bytes32 key,\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n glvWithdrawalHandler.simulateExecuteGlvWithdrawal(key, simulatedOracleParams);\n }\n\n function simulateExecuteLatestGlvWithdrawal(\n OracleUtils.SimulatePricesParams memory simulatedOracleParams\n ) external payable nonReentrant {\n bytes32 key = NonceUtils.getCurrentKey(dataStore);\n glvWithdrawalHandler.simulateExecuteGlvWithdrawal(key, simulatedOracleParams);\n }\n\n // makeExternalCalls can be used to perform an external swap before\n // an action\n // example:\n // - ExchangeRouter.sendTokens(token: WETH, receiver: externalHandler, amount: 1e18)\n // - ExchangeRouter.makeExternalCalls(\n // WETH.approve(spender: aggregator, amount: 1e18),\n // aggregator.swap(amount: 1, from: WETH, to: USDC, receiver: orderHandler)\n // )\n // - ExchangeRouter.createOrder\n // the msg.sender for makeExternalCalls would be externalHandler\n // refundTokens can be used to retrieve any excess tokens that may\n // be left in the externalHandler\n function makeExternalCalls(\n address[] memory externalCallTargets,\n bytes[] memory externalCallDataList,\n address[] memory refundTokens,\n address[] memory refundReceivers\n ) external payable nonReentrant {\n externalHandler.makeExternalCalls(\n externalCallTargets,\n externalCallDataList,\n refundTokens,\n refundReceivers\n );\n }\n}\n" + }, + "contracts/router/IExchangeRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../deposit/IDepositUtils.sol\";\nimport \"../withdrawal/IWithdrawalUtils.sol\";\nimport \"../oracle/OracleUtils.sol\";\nimport \"../shift/IShiftUtils.sol\";\nimport \"../order/IBaseOrderUtils.sol\";\n\ninterface IExchangeRouter {\n function createDeposit(\n IDepositUtils.CreateDepositParams calldata params\n ) external payable returns (bytes32);\n\n function cancelDeposit(bytes32 key) external payable;\n\n function createWithdrawal(\n IWithdrawalUtils.CreateWithdrawalParams calldata params\n ) external payable returns (bytes32);\n\n function cancelWithdrawal(bytes32 key) external payable;\n\n function executeAtomicWithdrawal(\n IWithdrawalUtils.CreateWithdrawalParams calldata params,\n OracleUtils.SetPricesParams calldata oracleParams\n ) external payable;\n\n function createShift(\n IShiftUtils.CreateShiftParams calldata params\n ) external payable returns (bytes32);\n\n function cancelShift(bytes32 key) external payable;\n\n function createOrder(\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external payable returns (bytes32);\n\n function updateOrder(\n bytes32 key,\n uint256 sizeDeltaUsd,\n uint256 acceptablePrice,\n uint256 triggerPrice,\n uint256 minOutputAmount,\n uint256 validFromTime,\n bool autoCancel\n ) external payable;\n\n function cancelOrder(bytes32 key) external payable;\n}\n" + }, + "contracts/router/relay/BaseGelatoRelayRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport {GelatoRelayContext} from \"@gelatonetwork/relay-context/contracts/GelatoRelayContext.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../../data/DataStore.sol\";\nimport \"../../exchange/IOrderHandler.sol\";\nimport \"../../external/IExternalHandler.sol\";\nimport \"../../feature/FeatureUtils.sol\";\nimport \"../../oracle/OracleModule.sol\";\nimport \"../../order/IBaseOrderUtils.sol\";\nimport \"../../order/OrderStoreUtils.sol\";\nimport \"../../order/OrderVault.sol\";\nimport \"../../router/BaseRouter.sol\";\nimport \"../../router/Router.sol\";\nimport \"../../token/TokenUtils.sol\";\nimport \"../../gas/GasUtils.sol\";\n\nimport \"./RelayUtils.sol\";\n\n\n/*\n * For gasless actions the funds are deducted from account.\n * Account must have enough funds to pay fees, regardless of the recipient's balance.\n */\nabstract contract BaseGelatoRelayRouter is GelatoRelayContext, ReentrancyGuard, OracleModule, BaseRouter {\n using Order for Order.Props;\n using SafeERC20 for IERC20;\n\n IOrderHandler public immutable orderHandler;\n OrderVault public immutable orderVault;\n ISwapHandler public immutable swapHandler;\n IExternalHandler public immutable externalHandler;\n\n mapping(bytes32 => bool) public digests; // Store digests to prevent duplicate transactions\n\n modifier withRelay(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bool isSubaccount\n ) {\n uint256 startingGas = gasleft();\n _validateGaslessFeature();\n Contracts memory contracts = _getContracts();\n _handleRelayBeforeAction(contracts, relayParams, account, srcChainId, isSubaccount);\n _;\n _handleRelayAfterAction(contracts, startingGas, account, srcChainId);\n }\n\n constructor(\n IOracle _oracle,\n IOrderHandler _orderHandler,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IExternalHandler _externalHandler\n ) OracleModule(_oracle) {\n orderHandler = _orderHandler;\n orderVault = _orderVault;\n swapHandler = _swapHandler;\n externalHandler = _externalHandler;\n }\n\n function _getContracts() internal view returns (Contracts memory contracts) {\n DataStore _dataStore = dataStore;\n address wnt = TokenUtils.wnt(_dataStore);\n contracts = Contracts({dataStore: _dataStore, orderVault: orderVault, swapHandler: swapHandler, wnt: wnt});\n }\n\n function _batch(\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams[] calldata createOrderParamsList,\n IRelayUtils.UpdateOrderParams[] calldata updateOrderParamsList,\n bytes32[] calldata cancelOrderKeys,\n bool isSubaccount\n ) internal returns (bytes32[] memory) {\n uint256 actionsCount = createOrderParamsList.length + updateOrderParamsList.length + cancelOrderKeys.length;\n if (actionsCount == 0) {\n revert Errors.RelayEmptyBatch();\n }\n\n bytes32[] memory orderKeys = new bytes32[](createOrderParamsList.length);\n for (uint256 i = 0; i < createOrderParamsList.length; i++) {\n orderKeys[i] = _createOrder(account, srcChainId, createOrderParamsList[i], isSubaccount);\n }\n\n for (uint256 i = 0; i < updateOrderParamsList.length; i++) {\n _updateOrder(account, updateOrderParamsList[i], isSubaccount);\n }\n\n for (uint256 i = 0; i < cancelOrderKeys.length; i++) {\n _cancelOrder(account, cancelOrderKeys[i]);\n }\n\n return orderKeys;\n }\n\n function _createOrder(\n address account,\n uint256 srcChainId,\n IBaseOrderUtils.CreateOrderParams calldata params,\n bool isSubaccount\n ) internal returns (bytes32) {\n Contracts memory contracts = _getContracts();\n IERC20(contracts.wnt).safeTransfer(address(contracts.orderVault), params.numbers.executionFee);\n\n if (\n params.numbers.initialCollateralDeltaAmount != 0 &&\n (Order.isSwapOrder(params.orderType) || Order.isIncreaseOrder(params.orderType))\n ) {\n // for increase and swap orders OrderUtils sets initialCollateralDeltaAmount based on the amount of received initialCollateralToken\n // instead of using initialCollateralDeltaAmount from params\n // it is possible to use external calls to send tokens to OrderVault, in this case initialCollateralDeltaAmount could be zero\n // and there is no need to call _sendTokens here\n _sendTokens(\n account,\n params.addresses.initialCollateralToken,\n address(contracts.orderVault),\n params.numbers.initialCollateralDeltaAmount,\n srcChainId\n );\n }\n\n return\n orderHandler.createOrder(account, srcChainId, params, isSubaccount && params.addresses.callbackContract != address(0));\n }\n\n function _updateOrder(address account, IRelayUtils.UpdateOrderParams calldata params, bool isSubaccount) internal {\n Contracts memory contracts = _getContracts();\n Order.Props memory order = OrderStoreUtils.get(contracts.dataStore, params.key);\n\n if (order.account() == address(0)) {\n revert Errors.EmptyOrder();\n }\n\n if (order.account() != account) {\n revert Errors.Unauthorized(account, \"account for updateOrder\");\n }\n\n if (params.executionFeeIncrease != 0) {\n IERC20(contracts.wnt).safeTransfer(address(contracts.orderVault), params.executionFeeIncrease);\n }\n\n orderHandler.updateOrder(\n params.key,\n params.sizeDeltaUsd,\n params.acceptablePrice,\n params.triggerPrice,\n params.minOutputAmount,\n params.validFromTime,\n params.autoCancel,\n order,\n // shouldCapMaxExecutionFee\n // see GasUtils.validateExecutionFee\n isSubaccount && order.callbackContract() != address(0) && params.executionFeeIncrease != 0\n );\n }\n\n function _cancelOrder(address account, bytes32 key) internal {\n Contracts memory contracts = _getContracts();\n Order.Props memory order = OrderStoreUtils.get(contracts.dataStore, key);\n if (order.account() == address(0)) {\n revert Errors.EmptyOrder();\n }\n\n if (order.account() != account) {\n revert Errors.Unauthorized(account, \"account for cancelOrder\");\n }\n orderHandler.cancelOrder(key);\n }\n\n function _handleRelayBeforeAction(\n Contracts memory contracts,\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bool isSubaccount\n ) internal withOraclePricesForAtomicAction(relayParams.oracleParams) {\n _handleTokenPermits(relayParams.tokenPermits);\n _handleExternalCalls(account, srcChainId, relayParams.externalCalls, isSubaccount);\n\n _handleRelayFee(contracts, relayParams, account, srcChainId, isSubaccount);\n }\n\n function _handleExternalCalls(address account, uint256 srcChainId, IRelayUtils.ExternalCalls calldata externalCalls, bool isSubaccount) internal {\n if (externalCalls.externalCallTargets.length == 0) {\n return;\n }\n\n if (isSubaccount) {\n // malicious subaccount could steal main account funds through external calls\n revert Errors.NonEmptyExternalCallsForSubaccountOrder();\n }\n\n if (\n externalCalls.sendTokens.length == 0 || externalCalls.sendTokens.length != externalCalls.sendAmounts.length\n ) {\n revert Errors.InvalidExternalCalls(externalCalls.sendTokens.length, externalCalls.sendAmounts.length);\n }\n\n for (uint256 i = 0; i < externalCalls.sendTokens.length; i++) {\n _sendTokens(account, externalCalls.sendTokens[i], address(externalHandler), externalCalls.sendAmounts[i], srcChainId);\n }\n\n externalHandler.makeExternalCalls(\n externalCalls.externalCallTargets,\n externalCalls.externalCallDataList,\n externalCalls.refundTokens,\n externalCalls.refundReceivers\n );\n\n _recordRefundedAmounts(\n account,\n srcChainId,\n externalCalls.refundTokens,\n externalCalls.refundReceivers\n );\n }\n\n function _recordRefundedAmounts(\n address account,\n uint256 srcChainId,\n address[] calldata refundTokens,\n address[] calldata refundReceivers\n ) internal virtual {\n // intended to be overridden for multichain actions\n // where the refundReceiver is always the multichainVault\n // and user's `account` multichain balance is increased by the refunded amount\n }\n\n function _handleTokenPermits(IRelayUtils.TokenPermit[] calldata tokenPermits) internal {\n // not all tokens support ERC20Permit, for them separate transaction is needed\n\n if (tokenPermits.length == 0) {\n return;\n }\n\n address _router = address(router);\n\n for (uint256 i; i < tokenPermits.length; i++) {\n IRelayUtils.TokenPermit memory permit = tokenPermits[i];\n\n if (permit.spender != _router) {\n // to avoid permitting spending by an incorrect spender for extra safety\n revert Errors.InvalidPermitSpender(permit.spender, _router);\n }\n\n try\n IERC20Permit(permit.token).permit(\n permit.owner,\n permit.spender,\n permit.value,\n permit.deadline,\n permit.v,\n permit.r,\n permit.s\n )\n {} catch {}\n }\n }\n\n function _handleRelayFee(\n Contracts memory contracts,\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n uint256 srcChainId,\n bool isSubaccount\n ) internal {\n // we do not return early here even if isRelayFeeExcluded is true\n // for the msg.sender\n // this would allow fee tokens to still be swapped if needed\n if (_isGelatoRelay(msg.sender) && _getFeeToken() != contracts.wnt) {\n revert Errors.UnsupportedRelayFeeToken(_getFeeToken(), contracts.wnt);\n }\n\n if (relayParams.fee.feeSwapPath.length != 0) {\n if (isSubaccount) {\n // a malicious subaccount could create a large swap with a negative price impact\n // and then execute a personal swap with a positive price impact\n // to mitigate this, we limit the max relay fee swap size for subaccounts\n uint256 maxRelayFeeSwapUsd = contracts.dataStore.getUint(Keys.MAX_RELAY_FEE_SWAP_USD_FOR_SUBACCOUNT);\n uint256 relayFeeUsd = relayParams.fee.feeAmount * oracle.getPrimaryPrice(relayParams.fee.feeToken).max;\n if (relayFeeUsd > maxRelayFeeSwapUsd) {\n revert Errors.MaxRelayFeeSwapForSubaccountExceeded(relayFeeUsd, maxRelayFeeSwapUsd);\n }\n }\n\n // send tokens to the orderVault to swap\n _sendTokens(account, relayParams.fee.feeToken, address(contracts.orderVault), relayParams.fee.feeAmount, srcChainId);\n // swapFeeTokens will swap the tokens and send the output tokens to address(this)\n RelayUtils.swapFeeTokens(contracts, eventEmitter, oracle, relayParams.fee);\n } else if (relayParams.fee.feeToken == contracts.wnt) {\n // fee tokens could be sent through external calls\n // in this case feeAmount could be 0 and there is no need to call _sendTokens\n if (relayParams.fee.feeAmount != 0) {\n _sendTokens(account, relayParams.fee.feeToken, address(this), relayParams.fee.feeAmount, srcChainId);\n }\n } else {\n revert Errors.UnexpectedRelayFeeToken(relayParams.fee.feeToken, contracts.wnt);\n }\n }\n\n // Gelato Relay Router contracts support 2 types of calls which have different logic for paying the relay fee:\n // 1. callWithSyncFee\n // 2. sponsoredCall\n //\n // callWithSyncFee:\n // - GMX contracts pay relay fee to the Gelato Relay within the same transaction\n // - the fee amount is calculated on Gelato Relay side, it depends on the gas used, gas price and conversion rate\n // - UI should retrieve the fee amount from the Gelato API\n //\n // sponsoredCall:\n // - GMX contracts do not pay Gelato Relay directly, instead Gelato 1Balance is used to cover the cost\n // - GMX contracts charge users for the call and deposit funds to `RELAY_FEE_ADDRESS`;\n // these funds will later be used to top up Gelato 1Balance\n // - the fee amount is calculated on GMX side based on the gas used (contracts use an approximation\n // because it's impossible to calculate the exact amount), gas price and `GELATO_RELAY_FEE_MULTIPLIER_FACTOR`.\n // note the fee amount doesn't necessarily match gas limit * gas price.\n // for example, GELATO_RELAY_FEE_MULTIPLIER_FACTOR can be set lower to subsidize the fee\n // - UI should calculate the fee amount as:\n // gas limit * gas price * GELATO_RELAY_FEE_MULTIPLIER_FACTOR * some buffer to account for gas price variance\n // - the calculation logic could be found in GasUtils.payGelatoRelayFee\n function _handleRelayAfterAction(\n Contracts memory contracts,\n uint256 startingGas,\n address account,\n uint256 srcChainId\n ) internal {\n uint256 relayFee;\n uint256 residualFeeAmount = ERC20(contracts.wnt).balanceOf(address(this));\n\n /// @dev relay fee is excluded for calls made through the IMultichainProvider\n /// as the user already paid for execution on the source chain\n if (!dataStore.getBool(Keys.isRelayFeeExcludedKey(msg.sender))) {\n bool isSponsoredCall = !_isGelatoRelay(msg.sender);\n if (isSponsoredCall) {\n relayFee = GasUtils.payGelatoRelayFee(\n contracts.dataStore,\n contracts.wnt,\n startingGas,\n msg.data.length,\n residualFeeAmount\n );\n } else {\n relayFee = _getFee();\n\n if (relayFee > residualFeeAmount) {\n revert Errors.InsufficientRelayFee(relayFee, residualFeeAmount);\n }\n\n _transferRelayFee();\n }\n }\n\n residualFeeAmount -= relayFee;\n if (residualFeeAmount > 0) {\n // residual fee is sent back to the account\n _transferResidualFee(contracts.wnt, account, residualFeeAmount, srcChainId);\n }\n }\n\n function _sendTokens(address account, address token, address receiver, uint256 amount, uint256 /* srcChainId */) internal virtual {\n // srcChainId not used here, but necessary when overriding _sendTokens in MultichainRouter\n AccountUtils.validateReceiver(receiver);\n router.pluginTransfer(token, account, receiver, amount);\n }\n\n // for multichain actions, the residual fee is send back to MultichainVault and user's multichain balance is increased\n function _transferResidualFee(address wnt, address account, uint256 residualFee, uint256 /* srcChainId */) internal virtual {\n // srcChainId is used when overriding _transferResidualFee in MultichainRouter\n IERC20(wnt).safeTransfer(account, residualFee);\n }\n\n function _validateCall(IRelayUtils.RelayParams calldata relayParams, address account, bytes32 structHash, uint256 srcChainId) internal {\n _validateCallWithoutSignature(\n srcChainId,\n relayParams.desChainId,\n relayParams.deadline,\n relayParams.tokenPermits.length\n );\n\n bytes32 domainSeparator = RelayUtils.getDomainSeparator(srcChainId);\n bytes32 digest = ECDSA.toTypedDataHash(domainSeparator, structHash);\n\n _validateDigest(digest);\n\n RelayUtils.validateSignature(\n domainSeparator,\n digest,\n relayParams.signature,\n account,\n \"call\"\n );\n }\n\n function _isMultichain() internal pure virtual returns (bool) {\n return false;\n }\n\n function _validateDeadline(uint256 deadline) internal view {\n if (block.timestamp > deadline) {\n revert Errors.DeadlinePassed(block.timestamp, deadline);\n }\n }\n\n /// @dev Once a transaction is signed and sent to a relay, it cannot be canceled.\n /// The user must wait for the expiresAt to pass.\n function _validateDigest(bytes32 digest) internal {\n if (digests[digest]) {\n revert Errors.InvalidUserDigest(digest);\n }\n digests[digest] = true;\n }\n\n function _validateGaslessFeature() internal view {\n FeatureUtils.validateFeature(dataStore, Keys.gaslessFeatureDisabledKey(address(this)));\n }\n\n function _validateCallWithoutSignature(uint256 srcChainId, uint256 desChainId, uint256 deadline, uint256 tokenPermitsLength) internal view {\n if (desChainId != block.chainid) {\n revert Errors.InvalidDestinationChainId(desChainId);\n }\n\n if (_isMultichain()) {\n // multichain\n if (tokenPermitsLength != 0) {\n revert Errors.TokenPermitsNotAllowedForMultichain();\n }\n if (!dataStore.getBool(Keys.isSrcChainIdEnabledKey(srcChainId))) {\n revert Errors.InvalidSrcChainId(srcChainId);\n }\n } else {\n // gasless\n if (srcChainId != block.chainid) {\n revert Errors.InvalidSrcChainId(srcChainId);\n }\n }\n\n _validateDeadline(deadline);\n }\n}\n" + }, + "contracts/router/relay/GelatoRelayRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../data/DataStore.sol\";\nimport \"../../event/EventEmitter.sol\";\nimport \"../../exchange/IOrderHandler.sol\";\nimport \"../../order/IBaseOrderUtils.sol\";\nimport \"../../order/OrderVault.sol\";\nimport \"../../router/Router.sol\";\nimport \"./BaseGelatoRelayRouter.sol\";\n\ncontract GelatoRelayRouter is BaseGelatoRelayRouter {\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n IOrderHandler _orderHandler,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IExternalHandler _externalHandler\n )\n BaseGelatoRelayRouter(_oracle, _orderHandler, _orderVault, _swapHandler, _externalHandler)\n BaseRouter(_router, _roleStore, _dataStore, _eventEmitter)\n {}\n\n // @note all params except account should be part of the corresponding struct hash\n function batch(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n IRelayUtils.BatchParams calldata params\n )\n external\n nonReentrant\n withRelay(relayParams, account, 0, false) // srcChainId is the current block.chainId\n returns (bytes32[] memory)\n {\n bytes32 structHash = RelayUtils.getBatchStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, block.chainid /* srcChainId */);\n\n return\n _batch(\n account,\n 0, // srcChainId is the current block.chainId\n params.createOrderParamsList,\n params.updateOrderParamsList,\n params.cancelOrderKeys,\n false // isSubaccount\n );\n }\n\n // @note all params except account should be part of the corresponding struct hash\n function createOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n IBaseOrderUtils.CreateOrderParams calldata params\n )\n external\n nonReentrant\n withRelay(relayParams, account, 0, false) // srcChainId is the current block.chainId\n returns (bytes32)\n {\n bytes32 structHash = RelayUtils.getCreateOrderStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, block.chainid /* srcChainId */);\n\n return\n _createOrder(\n account,\n 0, // srcChainId is the current block.chainId\n params,\n false // isSubaccount\n );\n }\n\n // @note all params except account should be part of the corresponding struct hash\n function updateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n IRelayUtils.UpdateOrderParams calldata params\n ) external nonReentrant withRelay(relayParams, account, 0 /* srcChainId is the current block.chainId */, false) {\n bytes32 structHash = RelayUtils.getUpdateOrderStructHash(relayParams, params);\n _validateCall(relayParams, account, structHash, block.chainid /* srcChainId */);\n\n _updateOrder(\n account,\n params,\n false // isSubaccount\n );\n }\n\n // @note all params except account should be part of the corresponding struct hash\n function cancelOrder(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n bytes32 key\n ) external nonReentrant withRelay(relayParams, account, 0 /* srcChainId is the current block.chainId */, false) {\n bytes32 structHash = RelayUtils.getCancelOrderStructHash(relayParams, key);\n _validateCall(relayParams, account, structHash, block.chainid /* srcChainId */);\n\n _cancelOrder(account, key);\n }\n}\n" + }, + "contracts/router/relay/IRelayUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../oracle/OracleUtils.sol\";\nimport \"../../order/IBaseOrderUtils.sol\";\n\ninterface IRelayUtils {\n struct FeeParams {\n // 1. if no swap is needed then `feeToken` should be WNT address, `feeAmount` should be correct amount and `feeSwapPath` should be empty\n // 2. if GMX v2 swap is used to swap relay fee then `feeToken` should be the address of the input token,\n // `feeAmount` should be the amount of the input token enough to cover the relay fee in WNT, and `feeSwapPath` should be the list of markets\n // through which the input token should be swapped to get the output token\n // 3. if external calls are used then `feeToken` should be WNT address (even though the input token is different)\n // `feeAmount` should be 0 because the input token and amount will be specified in `externalCalls`\n // `feeSwapPath` should be empty\n address feeToken;\n uint256 feeAmount;\n address[] feeSwapPath;\n }\n\n struct TokenPermit {\n // EIP-2612 permit https://eips.ethereum.org/EIPS/eip-2612\n address owner;\n address spender;\n uint256 value;\n uint256 deadline;\n uint8 v;\n bytes32 r;\n bytes32 s;\n address token;\n }\n\n // external calls could be used to swap relay fee and/or position collateral\n // GMX v2 swaps consume relatively a lot of gas, so using external calls could reduce txn fee\n // for relay fee the funds should be sent to the RelayRouter contract\n // for position collateral the funds should be sent to the OrderVault contract\n //\n // @note when using external calls for position collateral and creating multiple orders via `batch()`\n // then the funds will be allocated to the first increase order because all external calls are processed first\n // and only then OrderVault's balance is used for order's initialCollateralDeltaAmount\n //\n // @note using external calls for position collateral and atomic swaps for relay fee at the same time should be done with caution\n // if position collateral and initial relay fee token are the same then the collateral will be lost\n // for example, a user wants to pay ARB to open a position with USDC as collateral and pay USDC as a relay fee\n // 1. external calls swap ARB for USDC and sends USDC to the OrderVault to use as position collateral\n // 2. USDC is sent to the OrderVault before the swap\n // 3. on swap OrderVault.tokenBalances are synced\n // 4. on order creation OrderVault.recordTransferInt returns 0\n // 5. the collateral is lost\n struct ExternalCalls {\n // Gelato Relay Router contracts do not support `multicall` and `sendTokens` methods\n // so all tokens and amounts should be specified here\n address[] sendTokens; // tokens to send to ExternalHandler\n uint256[] sendAmounts; // tokens amounts to send to ExternalHandler\n // lists of external calls to be made\n address[] externalCallTargets; // external targets to call\n bytes[] externalCallDataList; // external call data list\n // refundTokens and refundReceivers are used to send residual funds left in the ExchangeHandler\n // for example, if \"swapExactOut\" is used some amount of \"tokenIn\" could be lefts\n address[] refundTokens; // tokens to refund to user\n address[] refundReceivers; // receivers of the refunds\n }\n\n struct RelayParams {\n // oracle params are used for relay fee swap through GMX v2 pools\n // if swap is not needed then `oracleParams` values should be empty\n OracleUtils.SetPricesParams oracleParams;\n ExternalCalls externalCalls;\n // token permits could be used to approve spending of tokens by the Router contract\n // instead of sending separate approval transactions\n TokenPermit[] tokenPermits;\n FeeParams fee;\n // interface generates a random nonce\n uint256 userNonce;\n // deadline for the transaction. should be used for extra safety so signed message\n // can't be used in future if a user signs and forgets about it\n uint256 deadline;\n bytes signature;\n uint256 desChainId;\n }\n\n struct TransferRequests {\n address[] tokens;\n address[] receivers;\n uint256[] amounts;\n }\n\n struct BridgeOutParams {\n address token;\n uint256 amount;\n uint256 minAmountOut;\n address provider;\n bytes data; // provider specific data e.g. dstEid\n }\n\n // @note all params except account should be part of the corresponding struct hash\n struct UpdateOrderParams {\n bytes32 key;\n uint256 sizeDeltaUsd;\n uint256 acceptablePrice;\n uint256 triggerPrice;\n uint256 minOutputAmount;\n uint256 validFromTime;\n bool autoCancel;\n // should be non zero if order's execution fee should be increased\n // otherwise should be 0\n uint256 executionFeeIncrease;\n }\n\n struct BatchParams {\n IBaseOrderUtils.CreateOrderParams[] createOrderParamsList;\n UpdateOrderParams[] updateOrderParamsList;\n bytes32[] cancelOrderKeys;\n }\n}\n" + }, + "contracts/router/relay/RelayUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n\nimport \"../../data/DataStore.sol\";\nimport \"../../event/EventEmitter.sol\";\nimport \"../../order/OrderVault.sol\";\nimport \"../../oracle/IOracle.sol\";\nimport \"../../oracle/OracleUtils.sol\";\nimport \"../../market/MarketUtils.sol\";\nimport \"../../swap/ISwapUtils.sol\";\nimport { SubaccountApproval } from \"../../subaccount/SubaccountUtils.sol\";\n\nimport \"../../deposit/IDepositUtils.sol\";\nimport \"../../glv/glvDeposit/IGlvDepositUtils.sol\";\nimport \"../../withdrawal/IWithdrawalUtils.sol\";\nimport \"../../glv/glvWithdrawal/IGlvWithdrawalUtils.sol\";\nimport \"../../shift/IShiftUtils.sol\";\nimport \"../../swap/ISwapHandler.sol\";\n\nimport \"./IRelayUtils.sol\";\n\nstruct Contracts {\n DataStore dataStore;\n OrderVault orderVault;\n ISwapHandler swapHandler;\n address wnt;\n}\n\nstring constant UPDATE_ORDER_PARAMS = \"UpdateOrderParams(bytes32 key,uint256 sizeDeltaUsd,uint256 acceptablePrice,uint256 triggerPrice,uint256 minOutputAmount,uint256 validFromTime,bool autoCancel,uint256 executionFeeIncrease)\";\n\nstring constant CREATE_ORDER_ADDRESSES = \"CreateOrderAddresses(address receiver,address cancellationReceiver,address callbackContract,address uiFeeReceiver,address market,address initialCollateralToken,address[] swapPath)\";\nstring constant CREATE_ORDER_NUMBERS = \"CreateOrderNumbers(uint256 sizeDeltaUsd,uint256 initialCollateralDeltaAmount,uint256 triggerPrice,uint256 acceptablePrice,uint256 executionFee,uint256 callbackGasLimit,uint256 minOutputAmount,uint256 validFromTime)\";\n\nstring constant CREATE_ORDER_PARAMS_ROOT = \"CreateOrderParams(CreateOrderAddresses addresses,CreateOrderNumbers numbers,uint256 orderType,uint256 decreasePositionSwapType,bool isLong,bool shouldUnwrapNativeToken,bool autoCancel,bytes32 referralCode,bytes32[] dataList)\";\nstring constant CREATE_ORDER_PARAMS = string(\n abi.encodePacked(\n \"CreateOrderParams(CreateOrderAddresses addresses,CreateOrderNumbers numbers,uint256 orderType,uint256 decreasePositionSwapType,bool isLong,bool shouldUnwrapNativeToken,bool autoCancel,bytes32 referralCode,bytes32[] dataList)\",\n CREATE_ORDER_ADDRESSES,\n CREATE_ORDER_NUMBERS\n )\n);\n\nlibrary RelayUtils {\n bytes32 public constant UPDATE_ORDER_PARAMS_TYPEHASH = keccak256(bytes(UPDATE_ORDER_PARAMS));\n bytes32 public constant UPDATE_ORDER_TYPEHASH =\n keccak256(\n abi.encodePacked(\n \"UpdateOrder(address account,UpdateOrderParams params,bytes32 relayParams,bytes32 subaccountApproval)\",\n UPDATE_ORDER_PARAMS\n )\n );\n\n bytes32 public constant CANCEL_ORDER_TYPEHASH =\n keccak256(bytes(\"CancelOrder(address account,bytes32 key,bytes32 relayParams,bytes32 subaccountApproval)\"));\n\n bytes32 public constant CREATE_ORDER_NUMBERS_TYPEHASH = keccak256(bytes(CREATE_ORDER_NUMBERS));\n bytes32 public constant CREATE_ORDER_ADDRESSES_TYPEHASH = keccak256(bytes(CREATE_ORDER_ADDRESSES));\n bytes32 public constant CREATE_ORDER_PARAMS_TYPEHASH = keccak256(bytes(CREATE_ORDER_PARAMS));\n bytes32 public constant CREATE_ORDER_TYPEHASH =\n keccak256(\n abi.encodePacked(\n \"CreateOrder(address account,CreateOrderAddresses addresses,CreateOrderNumbers numbers,uint256 orderType,uint256 decreasePositionSwapType,bool isLong,bool shouldUnwrapNativeToken,bool autoCancel,bytes32 referralCode,bytes32[] dataList,bytes32 relayParams,bytes32 subaccountApproval)\",\n CREATE_ORDER_ADDRESSES,\n CREATE_ORDER_NUMBERS\n )\n );\n\n bytes32 public constant SUBACCOUNT_APPROVAL_TYPEHASH =\n keccak256(\n bytes(\n \"SubaccountApproval(address subaccount,bool shouldAdd,uint256 expiresAt,uint256 maxAllowedCount,bytes32 actionType,uint256 nonce,uint256 desChainId,uint256 deadline,bytes32 integrationId)\"\n )\n );\n\n bytes32 public constant MINIFIED_TYPEHASH = keccak256(bytes(\"Minified(bytes32 digest)\"));\n\n bytes32 public constant REMOVE_SUBACCOUNT_TYPEHASH =\n keccak256(bytes(\"RemoveSubaccount(address subaccount,bytes32 relayParams)\"));\n\n bytes32 public constant BATCH_TYPEHASH =\n keccak256(\n abi.encodePacked(\n \"Batch(address account,CreateOrderParams[] createOrderParamsList,UpdateOrderParams[] updateOrderParamsList,bytes32[] cancelOrderKeys,bytes32 relayParams,bytes32 subaccountApproval)\",\n // according to EIP-712 all types following the root type should be in alphabetical order\n // can't use CREATE_ORDER_PARAMS because the resulting order would be incorrect: CreateOrderParams, CreateOrderAddresses, CreateOrderNumbers\n // it should be CreateOrderAddresses, CreateOrderNumbers, CreateOrderParams\n CREATE_ORDER_ADDRESSES,\n CREATE_ORDER_NUMBERS,\n CREATE_ORDER_PARAMS_ROOT,\n UPDATE_ORDER_PARAMS\n )\n );\n\n // Multichain\n bytes32 public constant SET_TRADER_REFERRAL_CODE_TYPEHASH =\n keccak256(bytes(\"SetTraderReferralCode(bytes32 referralCode,bytes32 relayParams)\"));\n\n bytes32 public constant CREATE_DEPOSIT_TYPEHASH =\n keccak256(\n bytes(\n \"CreateDeposit(address[] transferTokens,address[] transferReceivers,uint256[] transferAmounts,CreateDepositAddresses addresses,uint256 minMarketTokens,bool shouldUnwrapNativeToken,uint256 executionFee,uint256 callbackGasLimit,bytes32[] dataList,bytes32 relayParams)CreateDepositAddresses(address receiver,address callbackContract,address uiFeeReceiver,address market,address initialLongToken,address initialShortToken,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n )\n );\n bytes32 public constant CREATE_DEPOSIT_ADDRESSES_TYPEHASH =\n keccak256(\n bytes(\n \"CreateDepositAddresses(address receiver,address callbackContract,address uiFeeReceiver,address market,address initialLongToken,address initialShortToken,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n )\n );\n\n bytes32 public constant CREATE_WITHDRAWAL_TYPEHASH =\n keccak256(\n bytes(\n \"CreateWithdrawal(address[] transferTokens,address[] transferReceivers,uint256[] transferAmounts,CreateWithdrawalAddresses addresses,uint256 minLongTokenAmount,uint256 minShortTokenAmount,bool shouldUnwrapNativeToken,uint256 executionFee,uint256 callbackGasLimit,bytes32[] dataList,bytes32 relayParams)CreateWithdrawalAddresses(address receiver,address callbackContract,address uiFeeReceiver,address market,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n )\n );\n bytes32 public constant CREATE_WITHDRAWAL_ADDRESSES_TYPEHASH =\n keccak256(\n bytes(\n \"CreateWithdrawalAddresses(address receiver,address callbackContract,address uiFeeReceiver,address market,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n )\n );\n\n bytes32 public constant CREATE_SHIFT_TYPEHASH =\n keccak256(\n bytes(\n \"CreateShift(address[] transferTokens,address[] transferReceivers,uint256[] transferAmounts,CreateShiftAddresses addresses,uint256 minMarketTokens,uint256 executionFee,uint256 callbackGasLimit,bytes32[] dataList,bytes32 relayParams)CreateShiftAddresses(address receiver,address callbackContract,address uiFeeReceiver,address fromMarket,address toMarket)\"\n )\n );\n bytes32 public constant CREATE_SHIFT_ADDRESSES_TYPEHASH =\n keccak256(\n bytes(\n \"CreateShiftAddresses(address receiver,address callbackContract,address uiFeeReceiver,address fromMarket,address toMarket)\"\n )\n );\n\n bytes32 public constant CREATE_GLV_DEPOSIT_TYPEHASH =\n keccak256(\n \"CreateGlvDeposit(address[] transferTokens,address[] transferReceivers,uint256[] transferAmounts,CreateGlvDepositAddresses addresses,uint256 minGlvTokens,uint256 executionFee,uint256 callbackGasLimit,bool shouldUnwrapNativeToken,bool isMarketTokenDeposit,bytes32[] dataList,bytes32 relayParams)CreateGlvDepositAddresses(address glv,address market,address receiver,address callbackContract,address uiFeeReceiver,address initialLongToken,address initialShortToken,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n );\n bytes32 public constant CREATE_GLV_DEPOSIT_ADDRESSES_TYPEHASH =\n keccak256(\n \"CreateGlvDepositAddresses(address glv,address market,address receiver,address callbackContract,address uiFeeReceiver,address initialLongToken,address initialShortToken,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n );\n\n bytes32 public constant CREATE_GLV_WITHDRAWAL_TYPEHASH =\n keccak256(\n \"CreateGlvWithdrawal(address[] transferTokens,address[] transferReceivers,uint256[] transferAmounts,CreateGlvWithdrawalAddresses addresses,uint256 minLongTokenAmount,uint256 minShortTokenAmount,bool shouldUnwrapNativeToken,uint256 executionFee,uint256 callbackGasLimit,bytes32[] dataList,bytes32 relayParams)CreateGlvWithdrawalAddresses(address receiver,address callbackContract,address uiFeeReceiver,address market,address glv,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n );\n bytes32 public constant CREATE_GLV_WITHDRAWAL_ADDRESSES_TYPEHASH =\n keccak256(\n \"CreateGlvWithdrawalAddresses(address receiver,address callbackContract,address uiFeeReceiver,address market,address glv,address[] longTokenSwapPath,address[] shortTokenSwapPath)\"\n );\n\n bytes32 public constant TRANSFER_REQUESTS_TYPEHASH =\n keccak256(bytes(\"TransferRequests(address[] tokens,address[] receivers,uint256[] amounts)\"));\n\n bytes32 public constant BRIDGE_OUT_TYPEHASH =\n keccak256(bytes(\"BridgeOut(address token,uint256 amount,uint256 minAmountOut,address provider,bytes data,bytes32 relayParams)\"));\n\n bytes32 public constant CLAIM_FUNDING_FEES_TYPEHASH =\n keccak256(bytes(\"ClaimFundingFees(address[] markets,address[] tokens,address receiver,bytes32 relayParams)\"));\n bytes32 public constant CLAIM_COLLATERAL_TYPEHASH =\n keccak256(\n bytes(\n \"ClaimCollateral(address[] markets,address[] tokens,uint256[] timeKeys,address receiver,bytes32 relayParams)\"\n )\n );\n bytes32 public constant CLAIM_AFFILIATE_REWARDS_TYPEHASH =\n keccak256(\n bytes(\"ClaimAffiliateRewards(address[] markets,address[] tokens,address receiver,bytes32 relayParams)\")\n );\n\n bytes32 public constant DOMAIN_SEPARATOR_TYPEHASH =\n keccak256(bytes(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"));\n bytes32 public constant DOMAIN_SEPARATOR_NAME_HASH = keccak256(bytes(\"GmxBaseGelatoRelayRouter\"));\n bytes32 public constant DOMAIN_SEPARATOR_VERSION_HASH = keccak256(bytes(\"1\"));\n\n address constant GMX_SIMULATION_ORIGIN = address(uint160(uint256(keccak256(\"GMX SIMULATION ORIGIN\"))));\n\n\n function getDomainSeparator(uint256 sourceChainId) external view returns (bytes32) {\n return\n keccak256(\n abi.encode(\n DOMAIN_SEPARATOR_TYPEHASH,\n DOMAIN_SEPARATOR_NAME_HASH,\n DOMAIN_SEPARATOR_VERSION_HASH,\n sourceChainId,\n address(this)\n )\n );\n }\n\n function validateSignature(\n bytes32 domainSeparator,\n bytes32 digest,\n bytes calldata signature,\n address expectedSigner,\n string memory signatureType\n ) external view {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(digest, signature);\n\n // allow to optionally skip signature validation for eth_estimateGas / eth_call if tx.origin is GMX_SIMULATION_ORIGIN\n // do not use address(0) to avoid relays accidentally skipping signature validation if they use address(0) as the origin\n if (tx.origin == GMX_SIMULATION_ORIGIN) {\n return;\n }\n\n if (error != ECDSA.RecoverError.NoError) {\n revert Errors.InvalidSignature(signatureType);\n }\n\n // for some cases, e.g. ledger, signing does not work because the payload\n // is too large\n // for these cases, the user can sign a minified structHash instead\n // the user should be shown the source data that was used to construct\n // the minified structHash so that they can verify it independently\n if (recovered != expectedSigner) {\n bytes32 minifiedStructHash = keccak256(\n abi.encode(\n MINIFIED_TYPEHASH,\n digest\n )\n );\n\n // since digest is already validated in BaseGelatoRelayRouter,\n // we do not call _validateDigest on minifiedDigest\n bytes32 minifiedDigest = ECDSA.toTypedDataHash(domainSeparator, minifiedStructHash);\n\n (address recoveredFromMinified, ECDSA.RecoverError errorFromMinified) = ECDSA.tryRecover(minifiedDigest, signature);\n\n if (errorFromMinified != ECDSA.RecoverError.NoError) {\n revert Errors.InvalidSignature(signatureType);\n }\n\n if (recoveredFromMinified != expectedSigner) {\n revert Errors.InvalidRecoveredSigner(signatureType, recovered, recoveredFromMinified, expectedSigner);\n }\n }\n }\n\n function swapFeeTokens(\n Contracts memory contracts,\n EventEmitter eventEmitter,\n IOracle oracle,\n IRelayUtils.FeeParams calldata fee\n ) external {\n // swap fee tokens to WNT\n MarketUtils.validateSwapPath(contracts.dataStore, fee.feeSwapPath);\n Market.Props[] memory swapPathMarkets = MarketUtils.getSwapPathMarkets(contracts.dataStore, fee.feeSwapPath);\n\n (address outputToken, ) = contracts.swapHandler.swap(\n ISwapUtils.SwapParams({\n dataStore: contracts.dataStore,\n eventEmitter: eventEmitter,\n oracle: oracle,\n bank: contracts.orderVault,\n key: bytes32(0),\n tokenIn: fee.feeToken,\n amountIn: fee.feeAmount,\n swapPathMarkets: swapPathMarkets,\n minOutputAmount: 0,\n receiver: address(this),\n uiFeeReceiver: address(0),\n shouldUnwrapNativeToken: false,\n swapPricingType: ISwapPricingUtils.SwapPricingType.AtomicSwap\n })\n );\n\n if (outputToken != contracts.wnt) {\n revert Errors.UnexpectedRelayFeeTokenAfterSwap(outputToken, contracts.wnt);\n }\n }\n\n function _getRelayParamsHash(IRelayUtils.RelayParams calldata relayParams) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n relayParams.oracleParams,\n relayParams.externalCalls,\n relayParams.tokenPermits,\n relayParams.fee,\n relayParams.userNonce,\n relayParams.deadline,\n relayParams.desChainId\n )\n );\n }\n\n function getRemoveSubaccountStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n address subaccount\n ) external pure returns (bytes32) {\n return keccak256(abi.encode(REMOVE_SUBACCOUNT_TYPEHASH, subaccount, _getRelayParamsHash(relayParams)));\n }\n\n function getSubaccountApprovalStructHash(\n SubaccountApproval calldata subaccountApproval\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n SUBACCOUNT_APPROVAL_TYPEHASH,\n subaccountApproval.subaccount,\n subaccountApproval.shouldAdd,\n subaccountApproval.expiresAt,\n subaccountApproval.maxAllowedCount,\n subaccountApproval.actionType,\n subaccountApproval.nonce,\n subaccountApproval.desChainId,\n subaccountApproval.deadline,\n subaccountApproval.integrationId\n )\n );\n }\n\n function getCreateOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n IBaseOrderUtils.CreateOrderParams memory params\n ) external pure returns (bytes32) {\n bytes32 relayParamsHash = _getRelayParamsHash(relayParams);\n bytes32 subaccountApprovalHash = keccak256(abi.encode(subaccountApproval));\n\n return\n keccak256(\n abi.encode(\n CREATE_ORDER_TYPEHASH,\n account,\n _getCreateOrderAddressesStructHash(params.addresses),\n _getCreateOrderNumbersStructHash(params.numbers),\n uint256(params.orderType),\n uint256(params.decreasePositionSwapType),\n params.isLong,\n params.shouldUnwrapNativeToken,\n params.autoCancel,\n params.referralCode,\n keccak256(abi.encodePacked(params.dataList)),\n relayParamsHash,\n subaccountApprovalHash\n )\n );\n }\n\n function getCreateOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IBaseOrderUtils.CreateOrderParams memory params\n ) external pure returns (bytes32) {\n bytes32 relayParamsHash = _getRelayParamsHash(relayParams);\n\n return\n keccak256(\n abi.encode(\n CREATE_ORDER_TYPEHASH,\n address(0),\n _getCreateOrderAddressesStructHash(params.addresses),\n _getCreateOrderNumbersStructHash(params.numbers),\n uint256(params.orderType),\n uint256(params.decreasePositionSwapType),\n params.isLong,\n params.shouldUnwrapNativeToken,\n params.autoCancel,\n params.referralCode,\n keccak256(abi.encodePacked(params.dataList)),\n relayParamsHash,\n bytes32(0)\n )\n );\n }\n\n function _getCreateOrderAddressesStructHash(\n IBaseOrderUtils.CreateOrderParamsAddresses memory addresses\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_ORDER_ADDRESSES_TYPEHASH,\n addresses.receiver,\n addresses.cancellationReceiver,\n addresses.callbackContract,\n addresses.uiFeeReceiver,\n addresses.market,\n addresses.initialCollateralToken,\n keccak256(abi.encodePacked(addresses.swapPath))\n )\n );\n }\n\n function _getCreateOrderNumbersStructHash(\n IBaseOrderUtils.CreateOrderParamsNumbers memory numbers\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_ORDER_NUMBERS_TYPEHASH,\n numbers.sizeDeltaUsd,\n numbers.initialCollateralDeltaAmount,\n numbers.triggerPrice,\n numbers.acceptablePrice,\n numbers.executionFee,\n numbers.callbackGasLimit,\n numbers.minOutputAmount,\n numbers.validFromTime\n )\n );\n }\n\n function getUpdateOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.UpdateOrderParams calldata params\n ) external pure returns (bytes32) {\n return _getUpdateOrderStructHash(relayParams, bytes32(0), address(0), params);\n }\n\n function getUpdateOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n IRelayUtils.UpdateOrderParams calldata params\n ) external pure returns (bytes32) {\n return _getUpdateOrderStructHash(relayParams, keccak256(abi.encode(subaccountApproval)), account, params);\n }\n\n function _getUpdateOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n bytes32 subaccountApprovalHash,\n address account,\n IRelayUtils.UpdateOrderParams calldata params\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n UPDATE_ORDER_TYPEHASH,\n account,\n _getUpdateOrderParamsStructHash(params),\n _getRelayParamsHash(relayParams),\n subaccountApprovalHash\n )\n );\n }\n\n function _getUpdateOrderParamsStructHash(IRelayUtils.UpdateOrderParams calldata params) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n UPDATE_ORDER_PARAMS_TYPEHASH,\n params.key,\n params.sizeDeltaUsd,\n params.acceptablePrice,\n params.triggerPrice,\n params.minOutputAmount,\n params.validFromTime,\n params.autoCancel,\n params.executionFeeIncrease\n )\n );\n }\n\n function getCancelOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n bytes32 key\n ) external pure returns (bytes32) {\n return _getCancelOrderStructHash(relayParams, keccak256(abi.encode(subaccountApproval)), account, key);\n }\n\n function getCancelOrderStructHash(IRelayUtils.RelayParams calldata relayParams, bytes32 key) external pure returns (bytes32) {\n return _getCancelOrderStructHash(relayParams, bytes32(0), address(0), key);\n }\n\n function _getCancelOrderStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n bytes32 subaccountApprovalHash,\n address account,\n bytes32 key\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CANCEL_ORDER_TYPEHASH,\n account,\n key,\n _getRelayParamsHash(relayParams),\n subaccountApprovalHash\n )\n );\n }\n\n function _getCreateOrderParamsStructHash(\n IBaseOrderUtils.CreateOrderParams calldata params\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_ORDER_PARAMS_TYPEHASH,\n _getCreateOrderAddressesStructHash(params.addresses),\n _getCreateOrderNumbersStructHash(params.numbers),\n uint256(params.orderType),\n uint256(params.decreasePositionSwapType),\n params.isLong,\n params.shouldUnwrapNativeToken,\n params.autoCancel,\n params.referralCode,\n keccak256(abi.encodePacked(params.dataList))\n )\n );\n }\n\n function getBatchStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n IRelayUtils.BatchParams calldata params\n ) external pure returns (bytes32) {\n return\n _getBatchStructHash(\n relayParams,\n keccak256(abi.encode(subaccountApproval)),\n account,\n params.createOrderParamsList,\n params.updateOrderParamsList,\n params.cancelOrderKeys\n );\n }\n\n function getBatchStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.BatchParams calldata params\n ) external pure returns (bytes32) {\n return\n _getBatchStructHash(\n relayParams,\n bytes32(0),\n address(0),\n params.createOrderParamsList,\n params.updateOrderParamsList,\n params.cancelOrderKeys\n );\n }\n\n function _getBatchStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n bytes32 subaccountApprovalHash,\n address account,\n IBaseOrderUtils.CreateOrderParams[] calldata createOrderParamsList,\n IRelayUtils.UpdateOrderParams[] calldata updateOrderParamsList,\n bytes32[] calldata cancelOrderKeys\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n BATCH_TYPEHASH,\n account,\n _getCreateOrderParamsListStructHash(createOrderParamsList),\n _getUpdateOrderParamsListStructHash(updateOrderParamsList),\n keccak256(abi.encodePacked(cancelOrderKeys)),\n _getRelayParamsHash(relayParams),\n subaccountApprovalHash\n )\n );\n }\n\n function _getCreateOrderParamsListStructHash(\n IBaseOrderUtils.CreateOrderParams[] calldata createOrderParamsList\n ) private pure returns (bytes32) {\n bytes32[] memory createOrderParamsStructHashes = new bytes32[](createOrderParamsList.length);\n for (uint256 i = 0; i < createOrderParamsList.length; i++) {\n createOrderParamsStructHashes[i] = _getCreateOrderParamsStructHash(createOrderParamsList[i]);\n }\n return keccak256(abi.encodePacked(createOrderParamsStructHashes));\n }\n\n function _getUpdateOrderParamsListStructHash(\n IRelayUtils.UpdateOrderParams[] calldata updateOrderParamsList\n ) private pure returns (bytes32) {\n bytes32[] memory updateOrderParamsStructHashes = new bytes32[](updateOrderParamsList.length);\n for (uint256 i = 0; i < updateOrderParamsList.length; i++) {\n updateOrderParamsStructHashes[i] = _getUpdateOrderParamsStructHash(updateOrderParamsList[i]);\n }\n return keccak256(abi.encodePacked(updateOrderParamsStructHashes));\n }\n\n //////////////////// MULTICHAIN ////////////////////\n\n function getTraderReferralCodeStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n bytes32 referralCode\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n SET_TRADER_REFERRAL_CODE_TYPEHASH,\n referralCode,\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function getClaimFundingFeesStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CLAIM_FUNDING_FEES_TYPEHASH,\n keccak256(abi.encodePacked(markets)),\n keccak256(abi.encodePacked(tokens)),\n receiver,\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function getClaimCollateralStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n address[] memory markets,\n address[] memory tokens,\n uint256[] memory timeKeys,\n address receiver\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CLAIM_COLLATERAL_TYPEHASH,\n keccak256(abi.encodePacked(markets)),\n keccak256(abi.encodePacked(tokens)),\n keccak256(abi.encodePacked(timeKeys)),\n receiver,\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function getClaimAffiliateRewardsStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n address[] memory markets,\n address[] memory tokens,\n address receiver\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CLAIM_AFFILIATE_REWARDS_TYPEHASH,\n keccak256(abi.encodePacked(markets)),\n keccak256(abi.encodePacked(tokens)),\n receiver,\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function getCreateDepositStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.TransferRequests calldata transferRequests,\n IDepositUtils.CreateDepositParams memory params\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_DEPOSIT_TYPEHASH,\n keccak256(abi.encodePacked(transferRequests.tokens)),\n keccak256(abi.encodePacked(transferRequests.receivers)),\n keccak256(abi.encodePacked(transferRequests.amounts)),\n _getCreateDepositAdressesStructHash(params.addresses),\n params.minMarketTokens,\n params.shouldUnwrapNativeToken,\n params.executionFee,\n params.callbackGasLimit,\n keccak256(abi.encodePacked(params.dataList)),\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function _getCreateDepositAdressesStructHash(\n IDepositUtils.CreateDepositParamsAddresses memory addresses\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_DEPOSIT_ADDRESSES_TYPEHASH,\n addresses.receiver,\n addresses.callbackContract,\n addresses.uiFeeReceiver,\n addresses.market,\n addresses.initialLongToken,\n addresses.initialShortToken,\n keccak256(abi.encodePacked(addresses.longTokenSwapPath)),\n keccak256(abi.encodePacked(addresses.shortTokenSwapPath))\n )\n );\n }\n\n function getCreateGlvDepositStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvDepositUtils.CreateGlvDepositParams memory params\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_GLV_DEPOSIT_TYPEHASH,\n keccak256(abi.encodePacked(transferRequests.tokens)),\n keccak256(abi.encodePacked(transferRequests.receivers)),\n keccak256(abi.encodePacked(transferRequests.amounts)),\n _getCreateGlvDepositAddressesStructHash(params.addresses),\n params.minGlvTokens,\n params.executionFee,\n params.callbackGasLimit,\n params.shouldUnwrapNativeToken,\n params.isMarketTokenDeposit,\n keccak256(abi.encodePacked(params.dataList)),\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function _getCreateGlvDepositAddressesStructHash(\n IGlvDepositUtils.CreateGlvDepositParamsAddresses memory addresses\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_GLV_DEPOSIT_ADDRESSES_TYPEHASH,\n addresses.glv,\n addresses.market,\n addresses.receiver,\n addresses.callbackContract,\n addresses.uiFeeReceiver,\n addresses.initialLongToken,\n addresses.initialShortToken,\n keccak256(abi.encodePacked(addresses.longTokenSwapPath)),\n keccak256(abi.encodePacked(addresses.shortTokenSwapPath))\n )\n );\n }\n\n function getCreateWithdrawalStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.TransferRequests calldata transferRequests,\n IWithdrawalUtils.CreateWithdrawalParams memory params\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_WITHDRAWAL_TYPEHASH,\n keccak256(abi.encodePacked(transferRequests.tokens)),\n keccak256(abi.encodePacked(transferRequests.receivers)),\n keccak256(abi.encodePacked(transferRequests.amounts)),\n _getCreateWithdrawalAddressesStructHash(params.addresses),\n params.minLongTokenAmount,\n params.minShortTokenAmount,\n params.shouldUnwrapNativeToken,\n params.executionFee,\n params.callbackGasLimit,\n keccak256(abi.encodePacked(params.dataList)),\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function _getCreateWithdrawalAddressesStructHash(\n IWithdrawalUtils.CreateWithdrawalParamsAddresses memory addresses\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_WITHDRAWAL_ADDRESSES_TYPEHASH,\n addresses.receiver,\n addresses.callbackContract,\n addresses.uiFeeReceiver,\n addresses.market,\n keccak256(abi.encodePacked(addresses.longTokenSwapPath)),\n keccak256(abi.encodePacked(addresses.shortTokenSwapPath))\n )\n );\n }\n\n function getCreateShiftStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.TransferRequests calldata transferRequests,\n IShiftUtils.CreateShiftParams memory params\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_SHIFT_TYPEHASH,\n keccak256(abi.encodePacked(transferRequests.tokens)),\n keccak256(abi.encodePacked(transferRequests.receivers)),\n keccak256(abi.encodePacked(transferRequests.amounts)),\n _getCreateShiftAddressesStructHash(params.addresses),\n params.minMarketTokens,\n params.executionFee,\n params.callbackGasLimit,\n keccak256(abi.encodePacked(params.dataList)),\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function _getCreateShiftAddressesStructHash(\n IShiftUtils.CreateShiftParamsAddresses memory addresses\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_SHIFT_ADDRESSES_TYPEHASH,\n addresses.receiver,\n addresses.callbackContract,\n addresses.uiFeeReceiver,\n addresses.fromMarket,\n addresses.toMarket\n )\n );\n }\n\n function getCreateGlvWithdrawalStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.TransferRequests calldata transferRequests,\n IGlvWithdrawalUtils.CreateGlvWithdrawalParams memory params\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_GLV_WITHDRAWAL_TYPEHASH,\n keccak256(abi.encodePacked(transferRequests.tokens)),\n keccak256(abi.encodePacked(transferRequests.receivers)),\n keccak256(abi.encodePacked(transferRequests.amounts)),\n _getCreateGlvWithdrawalAddressesStructHash(params.addresses),\n params.minLongTokenAmount,\n params.minShortTokenAmount,\n params.shouldUnwrapNativeToken,\n params.executionFee,\n params.callbackGasLimit,\n keccak256(abi.encodePacked(params.dataList)),\n _getRelayParamsHash(relayParams)\n )\n );\n }\n\n function _getCreateGlvWithdrawalAddressesStructHash(\n IGlvWithdrawalUtils.CreateGlvWithdrawalParamsAddresses memory addresses\n ) private pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CREATE_GLV_WITHDRAWAL_ADDRESSES_TYPEHASH,\n addresses.receiver,\n addresses.callbackContract,\n addresses.uiFeeReceiver,\n addresses.market,\n addresses.glv,\n keccak256(abi.encodePacked(addresses.longTokenSwapPath)),\n keccak256(abi.encodePacked(addresses.shortTokenSwapPath))\n )\n );\n }\n\n function getBridgeOutStructHash(\n IRelayUtils.RelayParams calldata relayParams,\n IRelayUtils.BridgeOutParams memory params\n ) external pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n BRIDGE_OUT_TYPEHASH,\n params.token,\n params.amount,\n params.minAmountOut,\n params.provider,\n keccak256(abi.encodePacked(params.data)),\n _getRelayParamsHash(relayParams)\n )\n );\n }\n}\n" + }, + "contracts/router/relay/SubaccountGelatoRelayRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../router/Router.sol\";\nimport \"./BaseGelatoRelayRouter.sol\";\nimport \"./SubaccountRouterUtils.sol\";\n\ncontract SubaccountGelatoRelayRouter is BaseGelatoRelayRouter {\n mapping(address => uint256) public subaccountApprovalNonces;\n\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOracle _oracle,\n IOrderHandler _orderHandler,\n OrderVault _orderVault,\n ISwapHandler _swapHandler,\n IExternalHandler _externalHandler\n )\n BaseGelatoRelayRouter(_oracle, _orderHandler, _orderVault, _swapHandler, _externalHandler)\n BaseRouter(_router, _roleStore, _dataStore, _eventEmitter)\n {}\n\n struct BatchVars {\n bytes32 structHash;\n uint256 actionsCount;\n }\n\n // @note all params except subaccount should be part of the corresponding struct hash\n function batch(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account,\n address subaccount,\n IRelayUtils.BatchParams calldata params\n )\n external\n nonReentrant\n withRelay(relayParams, account, 0, true) // srcChainId is the current block.chainId\n returns (bytes32[] memory)\n {\n BatchVars memory vars;\n vars.structHash = RelayUtils.getBatchStructHash(relayParams, subaccountApproval, account, params);\n _validateCall(relayParams, subaccount, vars.structHash, block.chainid /* srcChainId */);\n\n for (uint256 i = 0; i < params.createOrderParamsList.length; i++) {\n SubaccountUtils.validateCreateOrderParams(account, params.createOrderParamsList[i]);\n }\n\n vars.actionsCount =\n params.createOrderParamsList.length +\n params.updateOrderParamsList.length +\n params.cancelOrderKeys.length;\n\n _handleSubaccountOrderAction(\n account,\n subaccount,\n vars.actionsCount,\n subaccountApproval\n );\n\n return\n _batch(\n account,\n 0, // srcChainId is the current block.chainId\n params.createOrderParamsList,\n params.updateOrderParamsList,\n params.cancelOrderKeys,\n true // isSubaccount\n );\n }\n\n // @note all params except subaccount should be part of the corresponding struct hash\n function createOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n address subaccount,\n IBaseOrderUtils.CreateOrderParams calldata params\n )\n external\n nonReentrant\n withRelay(relayParams, account, 0, true) // srcChainId is the current block.chainId\n returns (bytes32)\n {\n bytes32 structHash = RelayUtils.getCreateOrderStructHash(relayParams, subaccountApproval, account, params);\n _validateCall(relayParams, subaccount, structHash, block.chainid /* srcChainId */);\n SubaccountUtils.validateCreateOrderParams(account, params);\n _handleSubaccountOrderAction(account, subaccount, 1, subaccountApproval);\n\n return\n _createOrder(\n account,\n 0, // srcChainId is the current block.chainId\n params,\n true // isSubaccount\n );\n }\n\n // @note all params except subaccount should be part of the corresponding struct hash\n function updateOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n address subaccount,\n IRelayUtils.UpdateOrderParams calldata params\n ) external nonReentrant withRelay(relayParams, account, 0 /* srcChainId is the current block.chainId */, true) {\n bytes32 structHash = RelayUtils.getUpdateOrderStructHash(relayParams, subaccountApproval, account, params);\n _validateCall(relayParams, subaccount, structHash, block.chainid /* srcChainId */);\n _handleSubaccountOrderAction(account, subaccount, 1, subaccountApproval);\n\n _updateOrder(\n account,\n params,\n true // isSubaccount\n );\n }\n\n // @note all params except subaccount should be part of the corresponding struct hash\n function cancelOrder(\n IRelayUtils.RelayParams calldata relayParams,\n SubaccountApproval calldata subaccountApproval,\n address account, // main account\n address subaccount,\n bytes32 key\n ) external nonReentrant withRelay(relayParams, account, 0 /* srcChainId is the current block.chainId */, true) {\n bytes32 structHash = RelayUtils.getCancelOrderStructHash(relayParams, subaccountApproval, account, key);\n _validateCall(relayParams, subaccount, structHash, block.chainid /* srcChainId */);\n _handleSubaccountOrderAction(account, subaccount, 1, subaccountApproval);\n _cancelOrder(account, key);\n }\n\n // @note all params except account should be part of the corresponding struct hash\n function removeSubaccount(\n IRelayUtils.RelayParams calldata relayParams,\n address account,\n address subaccount\n ) external nonReentrant withRelay(relayParams, account, 0 /* srcChainId is the current block.chainId */, false) {\n // isSubaccount=false is passed to `withRelay` modifier because this action is signed by the main account\n bytes32 structHash = RelayUtils.getRemoveSubaccountStructHash(relayParams, subaccount);\n _validateCall(relayParams, account, structHash, block.chainid /* srcChainId */);\n\n SubaccountUtils.removeSubaccount(dataStore, eventEmitter, account, subaccount);\n }\n\n function _handleSubaccountOrderAction(\n address account,\n address subaccount,\n uint256 actionsCount,\n SubaccountApproval calldata subaccountApproval\n ) private {\n SubaccountRouterUtils.handleSubaccountAction(\n dataStore,\n eventEmitter,\n account,\n block.chainid, // srcChainId\n subaccount,\n Keys.SUBACCOUNT_ORDER_ACTION, // actionType\n actionsCount,\n subaccountApproval,\n subaccountApprovalNonces\n );\n }\n}\n" + }, + "contracts/router/relay/SubaccountRouterUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../../order/IBaseOrderUtils.sol\";\nimport \"../../feature/FeatureUtils.sol\";\nimport \"../../subaccount/SubaccountUtils.sol\";\nimport \"./RelayUtils.sol\";\n\nlibrary SubaccountRouterUtils {\n function handleSubaccountAction(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n uint256 srcChainId,\n address subaccount,\n bytes32 actionType,\n uint256 actionsCount,\n SubaccountApproval calldata subaccountApproval,\n mapping(address => uint256) storage subaccountApprovalNonces\n ) external {\n FeatureUtils.validateFeature(dataStore, Keys.subaccountFeatureDisabledKey(address(this)));\n\n SubaccountUtils.validateIntegrationId(dataStore, account, subaccount);\n\n _handleSubaccountApproval(\n dataStore,\n eventEmitter,\n account,\n srcChainId,\n subaccountApproval,\n subaccountApprovalNonces\n );\n\n SubaccountUtils.handleSubaccountAction(dataStore, eventEmitter, account, subaccount, actionType, actionsCount);\n }\n\n function _handleSubaccountApproval(DataStore dataStore, EventEmitter eventEmitter, address account, uint256 srcChainId, SubaccountApproval calldata subaccountApproval, mapping(address => uint256) storage subaccountApprovalNonces) private {\n if (subaccountApproval.signature.length == 0) {\n return;\n }\n\n if (subaccountApproval.subaccount == address(0)) {\n revert Errors.InvalidSubaccountApprovalSubaccount();\n }\n\n if (subaccountApproval.desChainId != block.chainid) {\n revert Errors.InvalidSubaccountApprovalDesChainId(subaccountApproval.desChainId);\n }\n\n if (block.timestamp > subaccountApproval.deadline) {\n revert Errors.SubaccountApprovalDeadlinePassed(block.timestamp, subaccountApproval.deadline);\n }\n\n uint256 storedNonce = subaccountApprovalNonces[account];\n\n if (storedNonce != subaccountApproval.nonce) {\n revert Errors.InvalidSubaccountApprovalNonce(storedNonce, subaccountApproval.nonce);\n }\n\n subaccountApprovalNonces[account] = storedNonce + 1;\n\n bytes32 domainSeparator = RelayUtils.getDomainSeparator(srcChainId);\n bytes32 structHash = RelayUtils.getSubaccountApprovalStructHash(subaccountApproval);\n bytes32 digest = ECDSA.toTypedDataHash(domainSeparator, structHash);\n RelayUtils.validateSignature(\n domainSeparator,\n digest,\n subaccountApproval.signature,\n account,\n \"subaccount approval\"\n );\n\n SubaccountUtils.handleSubaccountApproval(dataStore, eventEmitter, account, subaccountApproval);\n }\n}\n" + }, + "contracts/router/Router.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../role/RoleModule.sol\";\n\n/**\n * @title Router\n * @dev Users will approve this router for token spenditures\n */\ncontract Router is RoleModule {\n using SafeERC20 for IERC20;\n\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n /**\n * @dev transfer the specified amount of tokens from the account to the receiver\n * @param token the token to transfer\n * @param account the account to transfer from\n * @param receiver the account to transfer to\n * @param amount the amount of tokens to transfer\n */\n function pluginTransfer(address token, address account, address receiver, uint256 amount) external onlyRouterPlugin {\n IERC20(token).safeTransferFrom(account, receiver, amount);\n }\n}\n" + }, + "contracts/router/SubaccountRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./BaseRouter.sol\";\nimport \"../exchange/IOrderHandler.sol\";\nimport \"../feature/FeatureUtils.sol\";\nimport \"../subaccount/SubaccountUtils.sol\";\nimport \"../order/OrderVault.sol\";\nimport \"../order/OrderStoreUtils.sol\";\n\ncontract SubaccountRouter is BaseRouter {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n using Order for Order.Props;\n\n IOrderHandler public immutable orderHandler;\n OrderVault public immutable orderVault;\n\n constructor(\n Router _router,\n RoleStore _roleStore,\n DataStore _dataStore,\n EventEmitter _eventEmitter,\n IOrderHandler _orderHandler,\n OrderVault _orderVault\n ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) {\n orderHandler = _orderHandler;\n orderVault = _orderVault;\n }\n\n receive() external payable {\n address wnt = TokenUtils.wnt(dataStore);\n if (msg.sender != wnt) {\n revert Errors.InvalidNativeTokenSender(msg.sender);\n }\n }\n\n function addSubaccount(address subaccount) external payable nonReentrant {\n address account = msg.sender;\n SubaccountUtils.addSubaccount(dataStore, eventEmitter, account, subaccount);\n }\n\n function removeSubaccount(address subaccount) external payable nonReentrant {\n address account = msg.sender;\n SubaccountUtils.removeSubaccount(dataStore, eventEmitter, account, subaccount);\n }\n\n function setSubaccountExpiresAt(\n address subaccount,\n bytes32 actionType,\n uint256 expiresAt\n ) external payable nonReentrant {\n address account = msg.sender;\n SubaccountUtils.setSubaccountExpiresAt(dataStore, eventEmitter, account, subaccount, actionType, expiresAt);\n }\n\n function setMaxAllowedSubaccountActionCount(\n address subaccount,\n bytes32 actionType,\n uint256 maxAllowedCount\n ) external payable nonReentrant {\n address account = msg.sender;\n\n SubaccountUtils.setMaxAllowedSubaccountActionCount(\n dataStore,\n eventEmitter,\n account,\n subaccount,\n actionType,\n maxAllowedCount\n );\n }\n\n function setSubaccountAutoTopUpAmount(\n address subaccount,\n uint256 amount\n ) external payable nonReentrant {\n address account = msg.sender;\n\n SubaccountUtils.setSubaccountAutoTopUpAmount(\n dataStore,\n eventEmitter,\n account,\n subaccount,\n amount\n );\n }\n\n function setIntegrationId(\n address subaccount,\n bytes32 integrationId\n ) external payable nonReentrant {\n address account = msg.sender;\n\n SubaccountUtils.setSubaccountIntegrationId(\n dataStore,\n eventEmitter,\n account,\n subaccount,\n integrationId\n );\n }\n\n function createOrder(\n address account,\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external payable nonReentrant returns (bytes32) {\n uint256 startingGas = gasleft();\n\n _handleSubaccountAction(account, Keys.SUBACCOUNT_ORDER_ACTION);\n\n SubaccountUtils.validateCreateOrderParams(account, params);\n\n if (\n params.orderType == Order.OrderType.MarketSwap ||\n params.orderType == Order.OrderType.LimitSwap ||\n params.orderType == Order.OrderType.MarketIncrease ||\n params.orderType == Order.OrderType.LimitIncrease ||\n params.orderType == Order.OrderType.StopIncrease\n ) {\n router.pluginTransfer(\n params.addresses.initialCollateralToken, // token\n account, // account\n address(orderVault), // receiver\n params.numbers.initialCollateralDeltaAmount // amount\n );\n }\n\n bytes32 key = orderHandler.createOrder(\n account,\n 0, // srcChainId is the current block.chainId\n params,\n params.addresses.callbackContract != address(0)\n );\n\n _autoTopUpSubaccount(\n account, // account\n msg.sender, // subaccount\n startingGas, // startingGas\n params.numbers.executionFee // executionFee\n );\n\n return key;\n }\n\n function updateOrder(\n bytes32 key,\n uint256 sizeDeltaUsd,\n uint256 acceptablePrice,\n uint256 triggerPrice,\n uint256 minOutputAmount,\n uint256 validFromTime,\n bool autoCancel\n ) external payable nonReentrant {\n uint256 startingGas = gasleft();\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n\n if (order.account() == address(0)) { revert Errors.EmptyOrder(); }\n\n _handleSubaccountAction(order.account(), Keys.SUBACCOUNT_ORDER_ACTION);\n\n orderHandler.updateOrder(\n key,\n sizeDeltaUsd,\n acceptablePrice,\n triggerPrice,\n minOutputAmount,\n validFromTime,\n autoCancel,\n order,\n order.callbackContract() != address(0)\n );\n\n _autoTopUpSubaccount(\n order.account(), // account\n msg.sender, // subaccount\n startingGas, // startingGas\n 0 // executionFee\n );\n }\n\n function cancelOrder(\n bytes32 key\n ) external payable nonReentrant {\n uint256 startingGas = gasleft();\n\n Order.Props memory order = OrderStoreUtils.get(dataStore, key);\n\n if (order.account() == address(0)) { revert Errors.EmptyOrder(); }\n\n _handleSubaccountAction(order.account(), Keys.SUBACCOUNT_ORDER_ACTION);\n\n orderHandler.cancelOrder(key);\n\n _autoTopUpSubaccount(\n order.account(), // account\n msg.sender, // subaccount\n startingGas, // startingGas\n 0 // executionFee\n );\n }\n\n function _handleSubaccountAction(address account, bytes32 actionType) internal {\n FeatureUtils.validateFeature(dataStore, Keys.subaccountFeatureDisabledKey(address(this)));\n\n address subaccount = msg.sender;\n\n SubaccountUtils.validateIntegrationId(dataStore, account, subaccount);\n\n SubaccountUtils.handleSubaccountAction(\n dataStore,\n eventEmitter,\n account,\n subaccount,\n actionType,\n 1\n );\n }\n\n // the subaccount is topped up with wrapped native tokens\n // the subaccount should separately unwrap the token as needed\n function _autoTopUpSubaccount(address account, address subaccount, uint256 startingGas, uint256 executionFee) internal {\n uint256 amount = SubaccountUtils.getSubaccountAutoTopUpAmount(dataStore, account, subaccount);\n if (amount == 0) {\n return;\n }\n\n IERC20 wnt = IERC20(dataStore.getAddress(Keys.WNT));\n\n if (wnt.allowance(account, address(router)) < amount) { return; }\n if (wnt.balanceOf(account) < amount) { return; }\n\n // cap the top up amount to the amount of native tokens used\n uint256 nativeTokensUsed = (startingGas - gasleft()) * tx.gasprice + executionFee;\n if (nativeTokensUsed < amount) { amount = nativeTokensUsed; }\n\n router.pluginTransfer(\n address(wnt), // token\n account, // account\n address(this), // receiver\n amount // amount\n );\n\n TokenUtils.withdrawAndSendNativeToken(\n dataStore,\n address(wnt),\n subaccount,\n amount\n );\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n\n eventEmitter.emitEventLog2(\n \"SubaccountAutoTopUp\",\n Cast.toBytes32(account),\n Cast.toBytes32(subaccount),\n eventData\n );\n }\n}\n" + }, + "contracts/safe/SafeUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// referenced from https://github.com/safe-global/safe-smart-account/blob/main/contracts/libraries/SignMessageLib.sol\n\ninterface ISafe {\n function domainSeparator() external view returns (bytes32);\n}\n\nlibrary SafeUtils {\n /**\n * @dev The precomputed EIP-712 type hash for the Safe message type.\n * Precomputed value of: `keccak256(\"SafeMessage(bytes message)\")`.\n */\n bytes32 private constant SAFE_MSG_TYPEHASH = 0x60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca;\n\n function getMessageHash(address safeAccount, bytes memory message) internal view returns (bytes32) {\n bytes32 safeMessageHash = keccak256(abi.encode(SAFE_MSG_TYPEHASH, keccak256(message)));\n return keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), ISafe(safeAccount).domainSeparator(), safeMessageHash));\n }\n}\n" + }, + "contracts/shift/IShiftUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IShiftUtils {\n struct CreateShiftParams {\n CreateShiftParamsAddresses addresses;\n uint256 minMarketTokens;\n uint256 executionFee;\n uint256 callbackGasLimit;\n bytes32[] dataList;\n }\n\n struct CreateShiftParamsAddresses {\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address fromMarket;\n address toMarket;\n }\n}\n" + }, + "contracts/shift/Shift.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nlibrary Shift {\n struct Props {\n Addresses addresses;\n Numbers numbers;\n bytes32[] _dataList;\n }\n\n struct Addresses {\n address account;\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address fromMarket;\n address toMarket;\n }\n\n struct Numbers {\n uint256 marketTokenAmount;\n uint256 minMarketTokens;\n uint256 updatedAtTime;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 srcChainId;\n }\n\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n function receiver(Props memory props) internal pure returns (address) {\n return props.addresses.receiver;\n }\n\n function setReceiver(Props memory props, address value) internal pure {\n props.addresses.receiver = value;\n }\n\n function callbackContract(Props memory props) internal pure returns (address) {\n return props.addresses.callbackContract;\n }\n\n function setCallbackContract(Props memory props, address value) internal pure {\n props.addresses.callbackContract = value;\n }\n\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.uiFeeReceiver;\n }\n\n function setUiFeeReceiver(Props memory props, address value) internal pure {\n props.addresses.uiFeeReceiver = value;\n }\n\n function fromMarket(Props memory props) internal pure returns (address) {\n return props.addresses.fromMarket;\n }\n\n function setFromMarket(Props memory props, address value) internal pure {\n props.addresses.fromMarket = value;\n }\n\n function toMarket(Props memory props) internal pure returns (address) {\n return props.addresses.toMarket;\n }\n\n function setToMarket(Props memory props, address value) internal pure {\n props.addresses.toMarket = value;\n }\n\n function marketTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.marketTokenAmount;\n }\n\n function setMarketTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.marketTokenAmount = value;\n }\n\n function minMarketTokens(Props memory props) internal pure returns (uint256) {\n return props.numbers.minMarketTokens;\n }\n\n function setMinMarketTokens(Props memory props, uint256 value) internal pure {\n props.numbers.minMarketTokens = value;\n }\n\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n\n function executionFee(Props memory props) internal pure returns (uint256) {\n return props.numbers.executionFee;\n }\n\n function setExecutionFee(Props memory props, uint256 value) internal pure {\n props.numbers.executionFee = value;\n }\n\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\n return props.numbers.callbackGasLimit;\n }\n\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\n props.numbers.callbackGasLimit = value;\n }\n\n function srcChainId(Props memory props) internal pure returns (uint256) {\n return props.numbers.srcChainId;\n }\n\n function setSrcChainId(Props memory props, uint256 value) internal pure {\n props.numbers.srcChainId = value;\n }\n\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\n return props._dataList;\n }\n\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\n props._dataList = value;\n }\n}\n" + }, + "contracts/shift/ShiftEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nimport \"./Shift.sol\";\n\nlibrary ShiftEventUtils {\n using Shift for Shift.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitShiftCreated(\n EventEmitter eventEmitter,\n bytes32 key,\n Shift.Props memory shift\n ) external {\n EventUtils.EventLogData memory eventData = createEventData(shift);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog2(\n \"ShiftCreated\",\n key,\n Cast.toBytes32(shift.account()),\n eventData\n );\n }\n\n function emitShiftExecuted(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n uint256 receivedMarketTokens\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"receivedMarketTokens\", receivedMarketTokens);\n\n eventEmitter.emitEventLog2(\n \"ShiftExecuted\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitShiftCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\n \"ShiftCancelled\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function createEventData(Shift.Props memory shift) public pure returns(EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(6);\n eventData.addressItems.setItem(0, \"account\", shift.account());\n eventData.addressItems.setItem(1, \"receiver\", shift.receiver());\n eventData.addressItems.setItem(2, \"callbackContract\", shift.callbackContract());\n eventData.addressItems.setItem(3, \"fromMarket\", shift.fromMarket());\n eventData.addressItems.setItem(4, \"toMarket\", shift.toMarket());\n eventData.addressItems.setItem(5, \"uiFeeReceiver\", shift.uiFeeReceiver());\n\n eventData.uintItems.initItems(6);\n eventData.uintItems.setItem(0, \"marketTokenAmount\", shift.marketTokenAmount());\n eventData.uintItems.setItem(1, \"minMarketTokens\", shift.minMarketTokens());\n eventData.uintItems.setItem(2, \"updatedAtTime\", shift.updatedAtTime());\n eventData.uintItems.setItem(3, \"executionFee\", shift.executionFee());\n eventData.uintItems.setItem(4, \"callbackGasLimit\", shift.callbackGasLimit());\n eventData.uintItems.setItem(5, \"srcChainId\", shift.srcChainId());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", shift.dataList());\n return eventData;\n }\n}\n" + }, + "contracts/shift/ShiftStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Shift.sol\";\n\nlibrary ShiftStoreUtils {\n using Shift for Shift.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant RECEIVER = keccak256(abi.encode(\"RECEIVER\"));\n bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode(\"CALLBACK_CONTRACT\"));\n bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode(\"UI_FEE_RECEIVER\"));\n bytes32 public constant FROM_MARKET = keccak256(abi.encode(\"FROM_MARKET\"));\n bytes32 public constant TO_MARKET = keccak256(abi.encode(\"TO_MARKET\"));\n\n bytes32 public constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode(\"MARKET_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_MARKET_TOKENS = keccak256(abi.encode(\"MIN_MARKET_TOKENS\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n bytes32 public constant EXECUTION_FEE = keccak256(abi.encode(\"EXECUTION_FEE\"));\n bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"CALLBACK_GAS_LIMIT\"));\n bytes32 public constant SRC_CHAIN_ID = keccak256(abi.encode(\"SRC_CHAIN_ID\"));\n\n bytes32 public constant DATA_LIST = keccak256(abi.encode(\"DATA_LIST\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (Shift.Props memory) {\n Shift.Props memory shift;\n if (!dataStore.containsBytes32(Keys.SHIFT_LIST, key)) {\n return shift;\n }\n\n shift.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n shift.setReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, RECEIVER))\n ));\n\n shift.setCallbackContract(dataStore.getAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n ));\n\n shift.setUiFeeReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n ));\n\n shift.setFromMarket(dataStore.getAddress(\n keccak256(abi.encode(key, FROM_MARKET))\n ));\n\n shift.setToMarket(dataStore.getAddress(\n keccak256(abi.encode(key, TO_MARKET))\n ));\n\n shift.setMarketTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n ));\n\n shift.setMinMarketTokens(dataStore.getUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS))\n ));\n\n shift.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n shift.setExecutionFee(dataStore.getUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n ));\n\n shift.setCallbackGasLimit(dataStore.getUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n ));\n\n shift.setSrcChainId(dataStore.getUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n ));\n\n shift.setDataList(dataStore.getBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n ));\n\n return shift;\n }\n\n function set(DataStore dataStore, bytes32 key, Shift.Props memory shift) external {\n dataStore.addBytes32(\n Keys.SHIFT_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountShiftListKey(shift.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n shift.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, RECEIVER)),\n shift.receiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT)),\n shift.callbackContract()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER)),\n shift.uiFeeReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, FROM_MARKET)),\n shift.fromMarket()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, TO_MARKET)),\n shift.toMarket()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),\n shift.marketTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS)),\n shift.minMarketTokens()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n shift.updatedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, EXECUTION_FEE)),\n shift.executionFee()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),\n shift.callbackGasLimit()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID)),\n shift.srcChainId()\n );\n\n dataStore.setBytes32Array(\n keccak256(abi.encode(key, DATA_LIST)),\n shift.dataList()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.SHIFT_LIST, key)) {\n revert Errors.ShiftNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.SHIFT_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountShiftListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, FROM_MARKET))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, TO_MARKET))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_MARKET_TOKENS))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n );\n\n dataStore.removeBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n );\n }\n\n function getShiftCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.SHIFT_LIST);\n }\n\n function getShiftKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.SHIFT_LIST, start, end);\n }\n\n function getAccountShiftCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountShiftListKey(account));\n }\n\n function getAccountShiftKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountShiftListKey(account), start, end);\n }\n}\n" + }, + "contracts/shift/ShiftUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\n\nimport \"./ShiftVault.sol\";\nimport \"./ShiftStoreUtils.sol\";\nimport \"./ShiftEventUtils.sol\";\nimport \"./IShiftUtils.sol\";\n\nimport \"../nonce/NonceUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\nimport \"../utils/AccountUtils.sol\";\nimport \"../market/MarketUtils.sol\";\n\nimport \"../deposit/DepositVault.sol\";\nimport \"../exchange/IDepositHandler.sol\";\nimport \"../exchange/IWithdrawalHandler.sol\";\n\nimport \"../multichain/IMultichainTransferRouter.sol\";\n\nlibrary ShiftUtils {\n using Deposit for Deposit.Props;\n using Withdrawal for Withdrawal.Props;\n using Shift for Shift.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n struct CreateShiftCache {\n uint256 estimatedGasLimit;\n uint256 oraclePriceCount;\n bytes32 key;\n }\n\n struct ExecuteShiftParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n ShiftVault shiftVault;\n IOracle oracle;\n IDepositHandler depositHandler;\n IWithdrawalHandler withdrawalHandler;\n ISwapHandler swapHandler;\n bytes32 key;\n address keeper;\n uint256 startingGas;\n }\n\n struct ExecuteShiftCache {\n Withdrawal.Props withdrawal;\n bytes32 withdrawalKey;\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams executeWithdrawalParams;\n Market.Props depositMarket;\n uint256 initialLongTokenAmount;\n uint256 initialShortTokenAmount;\n Deposit.Props deposit;\n bytes32 depositKey;\n IExecuteDepositUtils.ExecuteDepositParams executeDepositParams;\n uint256 receivedMarketTokens;\n }\n\n function createShift(\n DataStore dataStore,\n EventEmitter eventEmitter,\n ShiftVault shiftVault,\n address account,\n uint256 srcChainId,\n IShiftUtils.CreateShiftParams memory params\n ) external returns (bytes32) {\n AccountUtils.validateAccount(account);\n\n if (params.addresses.fromMarket == params.addresses.toMarket) {\n revert Errors.ShiftFromAndToMarketAreEqual(params.addresses.fromMarket);\n }\n\n // GMX_DATA_ACTION hash is reserved for bridging out tokens, which is not supported during shifts\n if (params.dataList.length != 0 && params.dataList[0] == Keys.GMX_DATA_ACTION) {\n revert Errors.BridgeOutNotSupportedDuringShift();\n }\n\n address wnt = TokenUtils.wnt(dataStore);\n uint256 wntAmount = shiftVault.recordTransferIn(wnt);\n\n if (wntAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);\n }\n\n AccountUtils.validateReceiver(params.addresses.receiver);\n\n uint256 marketTokenAmount = shiftVault.recordTransferIn(params.addresses.fromMarket);\n\n if (marketTokenAmount == 0) {\n revert Errors.EmptyShiftAmount();\n }\n\n params.executionFee = wntAmount;\n\n Market.Props memory fromMarket = MarketUtils.getEnabledMarket(dataStore, params.addresses.fromMarket);\n Market.Props memory toMarket = MarketUtils.getEnabledMarket(dataStore, params.addresses.toMarket);\n\n if (fromMarket.longToken != toMarket.longToken) {\n revert Errors.LongTokensAreNotEqual(fromMarket.longToken, toMarket.longToken);\n }\n\n if (fromMarket.shortToken != toMarket.shortToken) {\n revert Errors.ShortTokensAreNotEqual(fromMarket.shortToken, toMarket.shortToken);\n }\n\n Shift.Props memory shift = Shift.Props(\n Shift.Addresses(\n account,\n params.addresses.receiver,\n params.addresses.callbackContract,\n params.addresses.uiFeeReceiver,\n params.addresses.fromMarket,\n params.addresses.toMarket\n ),\n Shift.Numbers(\n marketTokenAmount,\n params.minMarketTokens,\n Chain.currentTimestamp(),\n params.executionFee,\n params.callbackGasLimit,\n srcChainId\n ),\n params.dataList\n );\n\n CallbackUtils.validateCallbackGasLimit(dataStore, shift.callbackGasLimit());\n\n CreateShiftCache memory cache;\n\n cache.estimatedGasLimit = GasUtils.estimateExecuteShiftGasLimit(dataStore, shift);\n cache.oraclePriceCount = GasUtils.estimateShiftOraclePriceCount();\n GasUtils.validateExecutionFee(dataStore, cache.estimatedGasLimit, params.executionFee, cache.oraclePriceCount);\n\n cache.key = NonceUtils.getNextKey(dataStore);\n\n ShiftStoreUtils.set(dataStore, cache.key, shift);\n\n ShiftEventUtils.emitShiftCreated(eventEmitter, cache.key, shift);\n\n return cache.key;\n }\n\n function executeShift(\n ExecuteShiftParams memory params,\n Shift.Props memory shift\n ) external returns (uint256) {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n ShiftStoreUtils.remove(params.dataStore, params.key, shift.account());\n\n if (shift.account() == address(0)) {\n revert Errors.EmptyShift();\n }\n\n if (shift.marketTokenAmount() == 0) {\n revert Errors.EmptyShiftAmount();\n }\n\n ExecuteShiftCache memory cache;\n\n cache.depositMarket = MarketStoreUtils.get(params.dataStore, shift.toMarket());\n\n // if a user sends tokens directly to the shiftVault\n // the recordTransferIn after the shift withdrawal would record\n // these additional tokens and perform a deposit on the combined\n // token amount (tokens directly sent + tokens withdrawn)\n //\n // a user could use this to avoid paying deposit fees\n //\n // call shiftVault.recordTransferIn before the withdrawal to prevent\n // this\n params.shiftVault.recordTransferIn(cache.depositMarket.longToken);\n params.shiftVault.recordTransferIn(cache.depositMarket.shortToken);\n\n // srcChainId must be zero for the withdrawal, so that the withdrawn\n // tokens would be sent to the ShiftVault wallet balance instead of the\n // ShiftVault multichain balance\n cache.withdrawal = Withdrawal.Props(\n Withdrawal.Addresses(\n shift.account(),\n address(params.shiftVault), // receiver\n address(0), // callbackContract\n shift.uiFeeReceiver(), // uiFeeReceiver\n shift.fromMarket(), // market\n new address[](0), // longTokenSwapPath\n new address[](0) // shortTokenSwapPath\n ),\n Withdrawal.Numbers(\n shift.marketTokenAmount(),\n 0, // minLongTokenAmount\n 0, // minShortTokenAmount\n shift.updatedAtTime(),\n 0, // executionFee\n 0, // callbackGasLimit\n 0 // srcChainId is the current block.chainId\n ),\n Withdrawal.Flags(\n false\n ),\n new bytes32[](0) // dataList\n );\n\n cache.withdrawalKey = NonceUtils.getNextKey(params.dataStore);\n params.dataStore.addBytes32(\n Keys.WITHDRAWAL_LIST,\n cache.withdrawalKey\n );\n WithdrawalEventUtils.emitWithdrawalCreated(\n params.eventEmitter,\n cache.withdrawalKey,\n cache.withdrawal,\n Withdrawal.WithdrawalType.Shift\n );\n\n cache.executeWithdrawalParams = IExecuteWithdrawalUtils.ExecuteWithdrawalParams(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n IMultichainTransferRouter(payable(0)),\n WithdrawalVault(payable(params.shiftVault)),\n params.oracle,\n params.swapHandler,\n cache.withdrawalKey,\n params.keeper,\n params.startingGas,\n ISwapPricingUtils.SwapPricingType.Shift\n );\n\n params.withdrawalHandler.executeWithdrawalFromController(\n cache.executeWithdrawalParams,\n cache.withdrawal\n );\n\n // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would\n // be non-zero, the initialShortTokenAmount would be zero\n cache.initialLongTokenAmount = params.shiftVault.recordTransferIn(cache.depositMarket.longToken);\n cache.initialShortTokenAmount = params.shiftVault.recordTransferIn(cache.depositMarket.shortToken);\n\n // set the uiFeeReceiver to the zero address since the ui fee was already paid\n // while executing the withdrawal\n // srcChainId should be the Shift srcChainId so that the GM tokens would\n // go into the appropriate balance either the user's wallet balance\n // or their multichain balance\n cache.deposit = Deposit.Props(\n Deposit.Addresses(\n shift.account(),\n shift.receiver(),\n address(0), // callbackContract\n address(0), // uiFeeReceiver\n shift.toMarket(), // market\n cache.depositMarket.longToken, // initialLongToken\n cache.depositMarket.shortToken, // initialShortToken\n new address[](0), // longTokenSwapPath\n new address[](0) // shortTokenSwapPath\n ),\n Deposit.Numbers(\n cache.initialLongTokenAmount,\n cache.initialShortTokenAmount,\n shift.minMarketTokens(),\n shift.updatedAtTime(),\n 0, // executionFee\n 0, // callbackGasLimit\n shift.srcChainId()\n ),\n Deposit.Flags(\n false // shouldUnwrapNativeToken\n ),\n new bytes32[](0) // dataList\n );\n\n cache.depositKey = NonceUtils.getNextKey(params.dataStore);\n params.dataStore.addBytes32(\n Keys.DEPOSIT_LIST,\n cache.depositKey\n );\n DepositEventUtils.emitDepositCreated(params.eventEmitter, cache.depositKey, cache.deposit, Deposit.DepositType.Shift);\n\n // price impact from changes in virtual inventory should be excluded\n // since the action of withdrawing and depositing should not result in\n // a net change of virtual inventory\n // shift.srcChainId should be used for the srcChainId here so that GM tokens\n // would go to the appropriate balance eitehr the user's wallet balance or multichain balance\n cache.executeDepositParams = IExecuteDepositUtils.ExecuteDepositParams(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n IMultichainTransferRouter(payable(0)),\n DepositVault(payable(params.shiftVault)),\n params.oracle,\n params.swapHandler,\n cache.depositKey,\n params.keeper,\n params.startingGas,\n ISwapPricingUtils.SwapPricingType.Shift,\n false // includeVirtualInventoryImpact\n );\n\n cache.receivedMarketTokens = params.depositHandler.executeDepositFromController(\n cache.executeDepositParams,\n cache.deposit\n );\n\n ShiftEventUtils.emitShiftExecuted(\n params.eventEmitter,\n params.key,\n shift.account(),\n cache.receivedMarketTokens\n );\n\n EventUtils.EventLogData memory eventData;\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"receivedMarketTokens\", cache.receivedMarketTokens);\n CallbackUtils.afterShiftExecution(params.key, shift, eventData);\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.shiftVault\n ),\n params.key,\n shift.callbackContract(),\n shift.executionFee(),\n params.startingGas,\n GasUtils.estimateShiftOraclePriceCount(),\n params.keeper,\n shift.receiver(),\n shift.srcChainId()\n );\n\n return cache.receivedMarketTokens;\n }\n\n function cancelShift(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n ShiftVault shiftVault,\n bytes32 key,\n address keeper,\n uint256 startingGas,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n startingGas -= gasleft() / 63;\n\n Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);\n\n if (shift.account() == address(0)) {\n revert Errors.EmptyShift();\n }\n\n if (shift.marketTokenAmount() == 0) {\n revert Errors.EmptyShiftAmount();\n }\n\n ShiftStoreUtils.remove(dataStore, key, shift.account());\n\n if (shift.srcChainId() == 0) {\n shiftVault.transferOut(\n shift.fromMarket(),\n shift.account(),\n shift.marketTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n } else {\n shiftVault.transferOut(\n shift.fromMarket(),\n address(multichainVault),\n shift.marketTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n shift.fromMarket(),\n shift.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n\n ShiftEventUtils.emitShiftCancelled(\n eventEmitter,\n key,\n shift.account(),\n reason,\n reasonBytes\n );\n\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterShiftCancellation(key, shift, eventData);\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n dataStore,\n eventEmitter,\n multichainVault,\n shiftVault\n ),\n key,\n shift.callbackContract(),\n shift.executionFee(),\n startingGas,\n GasUtils.estimateShiftOraclePriceCount(),\n keeper,\n shift.receiver(),\n shift.srcChainId()\n );\n }\n}\n" + }, + "contracts/shift/ShiftVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/StrictBank.sol\";\n\ncontract ShiftVault is StrictBank {\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\n}\n" + }, + "contracts/subaccount/SubaccountUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../utils/Cast.sol\";\nimport \"../order/IBaseOrderUtils.sol\";\n\nstruct SubaccountApproval {\n address subaccount;\n bool shouldAdd;\n uint256 expiresAt;\n uint256 maxAllowedCount;\n bytes32 actionType;\n uint256 nonce; // for replay attack protection\n uint256 desChainId;\n uint256 deadline;\n bytes32 integrationId;\n bytes signature;\n}\n\nlibrary SubaccountUtils {\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function validateCreateOrderParams(\n address account,\n IBaseOrderUtils.CreateOrderParams calldata params\n ) external pure {\n if (params.addresses.receiver != account) {\n revert Errors.InvalidReceiverForSubaccountOrder(params.addresses.receiver, account);\n }\n\n if (params.addresses.cancellationReceiver != address(0) && params.addresses.cancellationReceiver != account) {\n revert Errors.InvalidCancellationReceiverForSubaccountOrder(params.addresses.cancellationReceiver, account);\n }\n }\n\n function addSubaccount(DataStore dataStore, EventEmitter eventEmitter, address account, address subaccount) public {\n bytes32 setKey = Keys.subaccountListKey(account);\n dataStore.addAddress(setKey, subaccount);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventEmitter.emitEventLog2(\"AddSubaccount\", Cast.toBytes32(account), Cast.toBytes32(subaccount), eventData);\n }\n\n function removeSubaccount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address subaccount\n ) external {\n bytes32 setKey = Keys.subaccountListKey(account);\n dataStore.removeAddress(setKey, subaccount);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventEmitter.emitEventLog2(\"RemoveSubaccount\", Cast.toBytes32(account), Cast.toBytes32(subaccount), eventData);\n }\n\n function handleSubaccountApproval(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n SubaccountApproval calldata subaccountApproval\n ) external {\n if (subaccountApproval.maxAllowedCount > 0) {\n setMaxAllowedSubaccountActionCount(\n dataStore,\n eventEmitter,\n account,\n subaccountApproval.subaccount,\n subaccountApproval.actionType,\n subaccountApproval.maxAllowedCount\n );\n }\n\n if (subaccountApproval.expiresAt > 0) {\n setSubaccountExpiresAt(\n dataStore,\n eventEmitter,\n account,\n subaccountApproval.subaccount,\n subaccountApproval.actionType,\n subaccountApproval.expiresAt\n );\n }\n\n if (subaccountApproval.shouldAdd) {\n addSubaccount(dataStore, eventEmitter, account, subaccountApproval.subaccount);\n }\n }\n\n function handleSubaccountAction(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address subaccount,\n bytes32 actionType,\n uint256 actionsCount\n ) external {\n validateSubaccount(dataStore, account, subaccount);\n\n bytes32 key = Keys.subaccountActionCountKey(account, subaccount, actionType);\n uint256 nextValue = dataStore.incrementUint(key, actionsCount);\n _validateSubaccountActionCountAndExpiresAt(dataStore, account, subaccount, actionType, nextValue);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"nextValue\", nextValue);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"actionType\", actionType);\n\n eventEmitter.emitEventLog2(\n \"IncrementSubaccountActionCount\",\n Cast.toBytes32(account),\n Cast.toBytes32(subaccount),\n eventData\n );\n }\n\n function setSubaccountExpiresAt(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address subaccount,\n bytes32 actionType,\n uint256 expiresAt\n ) public {\n bytes32 key = Keys.subaccountExpiresAtKey(account, subaccount, actionType);\n dataStore.setUint(key, expiresAt);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"expiresAt\", expiresAt);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"actionType\", actionType);\n\n eventEmitter.emitEventLog2(\n \"SetSubaccountExpiresAt\",\n Cast.toBytes32(account),\n Cast.toBytes32(subaccount),\n eventData\n );\n }\n\n function setMaxAllowedSubaccountActionCount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address subaccount,\n bytes32 actionType,\n uint256 maxAllowedCount\n ) public {\n bytes32 key = Keys.maxAllowedSubaccountActionCountKey(account, subaccount, actionType);\n dataStore.setUint(key, maxAllowedCount);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"maxAllowedCount\", maxAllowedCount);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"actionType\", actionType);\n\n eventEmitter.emitEventLog2(\n \"SetMaxAllowedSubaccountActionCount\",\n Cast.toBytes32(account),\n Cast.toBytes32(subaccount),\n eventData\n );\n }\n\n function _validateSubaccountActionCountAndExpiresAt(\n DataStore dataStore,\n address account,\n address subaccount,\n bytes32 actionType,\n uint256 count\n ) private view {\n bytes32 expiresAtKey = Keys.subaccountExpiresAtKey(account, subaccount, actionType);\n uint256 expiresAt = dataStore.getUint(expiresAtKey);\n\n if (block.timestamp > expiresAt) {\n revert Errors.SubaccountApprovalExpired(account, subaccount, expiresAt, block.timestamp);\n }\n\n bytes32 maxCountKey = Keys.maxAllowedSubaccountActionCountKey(account, subaccount, actionType);\n uint256 maxCount = dataStore.getUint(maxCountKey);\n\n if (count > maxCount) {\n revert Errors.MaxSubaccountActionCountExceeded(account, subaccount, count, maxCount);\n }\n }\n\n function validateSubaccount(DataStore dataStore, address account, address subaccount) public view {\n bytes32 setKey = Keys.subaccountListKey(account);\n if (!dataStore.containsAddress(setKey, subaccount)) {\n revert Errors.SubaccountNotAuthorized(account, subaccount);\n }\n }\n\n function validateIntegrationId(\n DataStore dataStore,\n address account,\n address subaccount\n ) external view {\n bytes32 integrationId = dataStore.getBytes32(Keys.subaccountIntegrationIdKey(account, subaccount));\n bytes32 key = Keys.subaccountIntegrationDisabledKey(integrationId);\n if (dataStore.getBool(key)) {\n revert Errors.SubaccountIntegrationIdDisabled(integrationId);\n }\n }\n\n function getSubaccountAutoTopUpAmount(\n DataStore dataStore,\n address account,\n address subaccount\n ) external view returns (uint256) {\n bytes32 key = Keys.subaccountAutoTopUpAmountKey(account, subaccount);\n return dataStore.getUint(key);\n }\n\n function setSubaccountAutoTopUpAmount(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address subaccount,\n uint256 amount\n ) external {\n bytes32 key = Keys.subaccountAutoTopUpAmountKey(account, subaccount);\n\n dataStore.setUint(key, amount);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"amount\", amount);\n\n eventEmitter.emitEventLog2(\n \"SetSubaccountAutoTopUpAmount\",\n Cast.toBytes32(account),\n Cast.toBytes32(subaccount),\n eventData\n );\n }\n\n function setSubaccountIntegrationId(\n DataStore dataStore,\n EventEmitter eventEmitter,\n address account,\n address subaccount,\n bytes32 integrationId\n ) external {\n bytes32 key = Keys.subaccountIntegrationIdKey(account, subaccount);\n\n dataStore.setBytes32(key, integrationId);\n\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"account\", account);\n eventData.addressItems.setItem(1, \"subaccount\", subaccount);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"integrationId\", integrationId);\n\n eventEmitter.emitEventLog2(\n \"SetSubaccountIntegrationId\",\n Cast.toBytes32(account),\n Cast.toBytes32(subaccount),\n eventData\n );\n }\n}\n" + }, + "contracts/swap/ISwapHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./ISwapUtils.sol\";\n\ninterface ISwapHandler {\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256);\n}\n" + }, + "contracts/swap/ISwapUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../bank/Bank.sol\";\nimport \"../market/Market.sol\";\n\nimport \"../oracle/IOracle.sol\";\nimport \"../pricing/ISwapPricingUtils.sol\";\n\ninterface ISwapUtils {\n event SwapReverted(string reason, bytes reasonBytes);\n\n /**\n * @param dataStore The contract that provides access to data stored on-chain.\n * @param eventEmitter The contract that emits events.\n * @param oracle The contract that provides access to price data from oracles.\n * @param bank The contract providing the funds for the swap.\n * @param key An identifying key for the swap.\n * @param tokenIn The address of the token that is being swapped.\n * @param amountIn The amount of the token that is being swapped.\n * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.\n * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.\n * @param receiver The address to which the swapped tokens should be sent.\n * @param uiFeeReceiver The address of the ui fee receiver.\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\n */\n struct SwapParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n IOracle oracle;\n Bank bank;\n bytes32 key;\n address tokenIn;\n uint256 amountIn;\n Market.Props[] swapPathMarkets;\n uint256 minOutputAmount;\n address receiver;\n address uiFeeReceiver;\n bool shouldUnwrapNativeToken;\n ISwapPricingUtils.SwapPricingType swapPricingType;\n }\n}\n" + }, + "contracts/swap/SwapHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"../role/RoleModule.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./ISwapHandler.sol\";\n\n/**\n * @title SwapHandler\n * @dev A contract to help with swap functions\n */\ncontract SwapHandler is ISwapHandler, ReentrancyGuard, RoleModule {\n constructor(RoleStore _roleStore) RoleModule(_roleStore) {}\n\n /**\n * @dev perform a swap based on the given params\n * @param params SwapUtils.SwapParams\n * @return (outputToken, outputAmount)\n */\n function swap(\n ISwapUtils.SwapParams memory params\n )\n external\n nonReentrant\n onlyController\n returns (address, uint256)\n {\n return SwapUtils.swap(params);\n }\n}\n" + }, + "contracts/swap/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../pricing/SwapPricingUtils.sol\";\nimport \"../fee/FeeUtils.sol\";\n\nimport \"./ISwapUtils.sol\";\n\n/**\n * @title SwapUtils\n * @dev Library for swap functions\n */\nlibrary SwapUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n using Price for Price.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n /**\n * @param market The market in which the swap should be executed.\n * @param tokenIn The address of the token that is being swapped.\n * @param amountIn The amount of the token that is being swapped.\n * @param receiver The address to which the swapped tokens should be sent.\n * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.\n */\n struct _SwapParams {\n Market.Props market;\n address tokenIn;\n uint256 amountIn;\n address receiver;\n bool shouldUnwrapNativeToken;\n }\n\n /**\n * @param tokenOut The address of the token that is being received as part of the swap.\n * @param tokenInPrice The price of the token that is being swapped.\n * @param tokenOutPrice The price of the token that is being received as part of the swap.\n * @param amountIn The amount of the token that is being swapped.\n * @param amountOut The amount of the token that is being received as part of the swap.\n * @param poolAmountOut The total amount of the token that is being received by all users in the swap pool.\n */\n struct SwapCache {\n address tokenOut;\n Price.Props tokenInPrice;\n Price.Props tokenOutPrice;\n uint256 amountIn;\n uint256 amountInAfterFees;\n uint256 amountOut;\n uint256 poolAmountOut;\n int256 priceImpactUsd;\n int256 priceImpactAmount;\n bool balanceWasImproved;\n uint256 cappedDiffUsd;\n int256 tokenInPriceImpactAmount;\n }\n\n event SwapReverted(string reason, bytes reasonBytes);\n\n /**\n * @dev Swaps a given amount of a given token for another token based on a\n * specified swap path.\n * @param params The parameters for the swap.\n * @return A tuple containing the address of the token that was received as\n * part of the swap and the amount of the received token.\n */\n function swap(ISwapUtils.SwapParams memory params) external returns (address, uint256) {\n if (params.amountIn == 0) {\n return (params.tokenIn, params.amountIn);\n }\n\n if (params.swapPathMarkets.length == 0) {\n if (params.amountIn < params.minOutputAmount) {\n revert Errors.InsufficientOutputAmount(params.amountIn, params.minOutputAmount);\n }\n\n if (address(params.bank) != params.receiver) {\n params.bank.transferOut(\n params.tokenIn,\n params.receiver,\n params.amountIn,\n params.shouldUnwrapNativeToken\n );\n }\n\n return (params.tokenIn, params.amountIn);\n }\n\n Market.Props memory firstMarket = params.swapPathMarkets[0];\n if (address(params.bank) != firstMarket.marketToken) {\n // validate initialCollateralToken is a valid collateral token of the first\n // market in the swapPath ensuring tokenIn is not a malicious token\n // TOKEN_TRANSFER_GAS_LIMIT should prevent excessive gas consumption due to a malicious token as well\n if (params.tokenIn != firstMarket.longToken && params.tokenIn != firstMarket.shortToken) {\n revert Errors.InvalidTokenIn(params.tokenIn, firstMarket.marketToken);\n }\n params.bank.transferOut(params.tokenIn, firstMarket.marketToken, params.amountIn, false);\n }\n\n address tokenOut = params.tokenIn;\n uint256 outputAmount = params.amountIn;\n\n for (uint256 i; i < params.swapPathMarkets.length; i++) {\n Market.Props memory market = params.swapPathMarkets[i];\n\n bool flagExists = params.dataStore.getBool(Keys.swapPathMarketFlagKey(market.marketToken));\n if (flagExists) {\n revert Errors.DuplicatedMarketInSwapPath(market.marketToken);\n }\n\n params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), true);\n\n uint256 nextIndex = i + 1;\n address receiver;\n if (nextIndex < params.swapPathMarkets.length) {\n receiver = params.swapPathMarkets[nextIndex].marketToken;\n } else {\n receiver = params.receiver;\n }\n\n _SwapParams memory _params = _SwapParams(\n market,\n tokenOut,\n outputAmount,\n receiver,\n i == params.swapPathMarkets.length - 1 ? params.shouldUnwrapNativeToken : false // only convert ETH on the last swap if needed\n );\n\n (tokenOut, outputAmount) = _swap(params, _params);\n }\n\n for (uint256 i; i < params.swapPathMarkets.length; i++) {\n Market.Props memory market = params.swapPathMarkets[i];\n params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), false);\n }\n\n if (outputAmount < params.minOutputAmount) {\n revert Errors.InsufficientSwapOutputAmount(outputAmount, params.minOutputAmount);\n }\n\n return (tokenOut, outputAmount);\n }\n\n function validateSwapOutputToken(\n DataStore dataStore,\n address[] memory swapPath,\n address inputToken,\n address expectedOutputToken\n ) external view {\n address outputToken = getOutputToken(dataStore, swapPath, inputToken);\n if (outputToken != expectedOutputToken) {\n revert Errors.InvalidSwapOutputToken(outputToken, expectedOutputToken);\n }\n }\n\n function getOutputToken(\n DataStore dataStore,\n address[] memory swapPath,\n address inputToken\n ) public view returns (address) {\n address outputToken = inputToken;\n Market.Props[] memory markets = MarketUtils.getSwapPathMarkets(dataStore, swapPath);\n uint256 marketCount = markets.length;\n\n for (uint256 i; i < marketCount; i++) {\n Market.Props memory market = markets[i];\n outputToken = MarketUtils.getOppositeToken(outputToken, market);\n }\n\n return outputToken;\n }\n\n /**\n * Performs a swap on a single market.\n *\n * @param params The parameters for the swap.\n * @param _params The parameters for the swap on this specific market.\n * @return The token and amount that was swapped.\n */\n function _swap(ISwapUtils.SwapParams memory params, _SwapParams memory _params) internal returns (address, uint256) {\n SwapCache memory cache;\n\n if (_params.tokenIn != _params.market.longToken && _params.tokenIn != _params.market.shortToken) {\n revert Errors.InvalidTokenIn(_params.tokenIn, _params.market.marketToken);\n }\n\n MarketUtils.validateSwapMarket(params.dataStore, _params.market);\n\n cache.tokenOut = MarketUtils.getOppositeToken(_params.tokenIn, _params.market);\n cache.tokenInPrice = params.oracle.getPrimaryPrice(_params.tokenIn);\n cache.tokenOutPrice = params.oracle.getPrimaryPrice(cache.tokenOut);\n\n // note that this may not be entirely accurate since the effect of the\n // swap fees are not accounted for\n (cache.priceImpactUsd, cache.balanceWasImproved) = SwapPricingUtils.getPriceImpactUsd(\n SwapPricingUtils.GetPriceImpactUsdParams(\n params.dataStore,\n _params.market,\n _params.tokenIn,\n cache.tokenOut,\n cache.tokenInPrice.midPrice(),\n cache.tokenOutPrice.midPrice(),\n (_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(),\n -(_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(),\n true // includeVirtualInventoryImpact\n )\n );\n\n SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(\n params.dataStore,\n _params.market.marketToken,\n _params.amountIn,\n cache.balanceWasImproved,\n params.uiFeeReceiver,\n params.swapPricingType\n );\n\n bytes32 swapFeeType = params.swapPricingType == ISwapPricingUtils.SwapPricingType.AtomicSwap\n ? Keys.ATOMIC_SWAP_FEE_TYPE\n : Keys.SWAP_FEE_TYPE;\n\n FeeUtils.incrementClaimableFeeAmount(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n _params.tokenIn,\n fees.feeReceiverAmount,\n swapFeeType\n );\n\n FeeUtils.incrementClaimableUiFeeAmount(\n params.dataStore,\n params.eventEmitter,\n params.uiFeeReceiver,\n _params.market.marketToken,\n _params.tokenIn,\n fees.uiFeeAmount,\n Keys.UI_SWAP_FEE_TYPE\n );\n\n if (cache.priceImpactUsd > 0) {\n // when there is a positive price impact factor, additional tokens from the swap impact pool\n // are withdrawn for the user\n // for example, if 50,000 USDC is swapped out and there is a positive price impact\n // an additional 100 USDC may be sent to the user\n // the swap impact pool is decreased by the used amount\n\n cache.amountIn = fees.amountAfterFees;\n\n (cache.priceImpactAmount, cache.cappedDiffUsd) = MarketUtils.applySwapImpactWithCap(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n cache.tokenOut,\n cache.tokenOutPrice,\n cache.priceImpactUsd\n );\n\n // if the positive price impact was capped, use the tokenIn swap\n // impact pool to pay for the positive price impact\n if (cache.cappedDiffUsd != 0) {\n (cache.tokenInPriceImpactAmount /* uint256 cappedDiffUsd */, ) = MarketUtils.applySwapImpactWithCap(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n _params.tokenIn,\n cache.tokenInPrice,\n cache.cappedDiffUsd.toInt256()\n );\n\n // this additional amountIn is already in the Market\n // it is subtracted from the swap impact pool amount\n // and the market pool amount is increased by the updated\n // amountIn below\n cache.amountIn += cache.tokenInPriceImpactAmount.toUint256();\n }\n\n // round amountOut down\n cache.amountOut = (cache.amountIn * cache.tokenInPrice.min) / cache.tokenOutPrice.max;\n cache.poolAmountOut = cache.amountOut;\n\n // the below amount is subtracted from the swap impact pool instead of the market pool amount\n cache.amountOut += cache.priceImpactAmount.toUint256();\n } else {\n // when there is a negative price impact factor,\n // less of the input amount is sent to the pool\n // for example, if 10 ETH is swapped in and there is a negative price impact\n // only 9.995 ETH may be swapped in\n // the remaining 0.005 ETH will be stored in the swap impact pool\n\n (cache.priceImpactAmount /* uint256 cappedDiffUsd */, ) = MarketUtils.applySwapImpactWithCap(\n params.dataStore,\n params.eventEmitter,\n _params.market.marketToken,\n _params.tokenIn,\n cache.tokenInPrice,\n cache.priceImpactUsd\n );\n\n if (fees.amountAfterFees <= (-cache.priceImpactAmount).toUint256()) {\n revert Errors.SwapPriceImpactExceedsAmountIn(fees.amountAfterFees, cache.priceImpactAmount);\n }\n\n cache.amountIn = fees.amountAfterFees - (-cache.priceImpactAmount).toUint256();\n cache.amountOut = (cache.amountIn * cache.tokenInPrice.min) / cache.tokenOutPrice.max;\n cache.poolAmountOut = cache.amountOut;\n }\n\n // the amountOut value includes the positive price impact amount\n if (_params.receiver != _params.market.marketToken) {\n MarketToken(payable(_params.market.marketToken)).transferOut(\n cache.tokenOut,\n _params.receiver,\n cache.amountOut,\n _params.shouldUnwrapNativeToken\n );\n }\n\n MarketUtils.applyDeltaToPoolAmount(\n params.dataStore,\n params.eventEmitter,\n _params.market,\n _params.tokenIn,\n (cache.amountIn + fees.feeAmountForPool).toInt256()\n );\n\n // the poolAmountOut excludes the positive price impact amount\n // as that is deducted from the swap impact pool instead\n MarketUtils.applyDeltaToPoolAmount(\n params.dataStore,\n params.eventEmitter,\n _params.market,\n cache.tokenOut,\n -cache.poolAmountOut.toInt256()\n );\n\n MarketUtils.MarketPrices memory prices = MarketUtils.MarketPrices(\n params.oracle.getPrimaryPrice(_params.market.indexToken),\n _params.tokenIn == _params.market.longToken ? cache.tokenInPrice : cache.tokenOutPrice,\n _params.tokenIn == _params.market.shortToken ? cache.tokenInPrice : cache.tokenOutPrice\n );\n\n MarketUtils.validatePoolAmount(params.dataStore, _params.market, _params.tokenIn);\n\n // for single token markets cache.tokenOut will always equal _params.market.longToken\n // so only the reserve for longs will be validated\n // swaps should be disabled for single token markets so this should not be an issue\n MarketUtils.validateReserve(\n params.dataStore,\n _params.market,\n prices,\n cache.tokenOut == _params.market.longToken\n );\n\n MarketUtils.validateMaxPnl(\n params.dataStore,\n _params.market,\n prices,\n _params.tokenIn == _params.market.longToken\n ? Keys.MAX_PNL_FACTOR_FOR_DEPOSITS\n : Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n cache.tokenOut == _params.market.shortToken\n ? Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS\n : Keys.MAX_PNL_FACTOR_FOR_DEPOSITS\n );\n\n SwapPricingUtils.EmitSwapInfoParams memory emitSwapInfoParams;\n\n emitSwapInfoParams.orderKey = params.key;\n emitSwapInfoParams.market = _params.market.marketToken;\n emitSwapInfoParams.receiver = _params.receiver;\n emitSwapInfoParams.tokenIn = _params.tokenIn;\n emitSwapInfoParams.tokenOut = cache.tokenOut;\n emitSwapInfoParams.tokenInPrice = cache.tokenInPrice.min;\n emitSwapInfoParams.tokenOutPrice = cache.tokenOutPrice.max;\n emitSwapInfoParams.amountIn = _params.amountIn;\n emitSwapInfoParams.amountInAfterFees = fees.amountAfterFees;\n emitSwapInfoParams.amountOut = cache.amountOut;\n emitSwapInfoParams.priceImpactUsd = cache.priceImpactUsd;\n emitSwapInfoParams.priceImpactAmount = cache.priceImpactAmount;\n emitSwapInfoParams.tokenInPriceImpactAmount = cache.tokenInPriceImpactAmount;\n\n SwapPricingUtils.emitSwapInfo(params.eventEmitter, emitSwapInfoParams);\n\n SwapPricingUtils.emitSwapFeesCollected(\n params.eventEmitter,\n params.key,\n _params.market.marketToken,\n _params.tokenIn,\n cache.tokenInPrice.min,\n swapFeeType,\n fees\n );\n\n return (cache.tokenOut, cache.amountOut);\n }\n}\n" + }, + "contracts/test/ArrayTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Array.sol\";\n\n/**\n * @title ArrayTest\n * @dev Contract to help test the Array library\n */\ncontract ArrayTest {\n function getMedian(uint256[] memory arr) external pure returns (uint256) {\n return Array.getMedian(arr);\n }\n}\n" + }, + "contracts/test/DepositStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../deposit/DepositStoreUtils.sol\";\n\n/**\n * @title DepositeStoreUtilsTest\n * @dev Contract to help test the DepositStoreUtils library\n */\ncontract DepositStoreUtilsTest {\n function getEmptyDeposit() external pure returns (Deposit.Props memory) {\n Deposit.Props memory deposit;\n return deposit;\n }\n\n function setDeposit(DataStore dataStore, bytes32 key, Deposit.Props memory deposit) external {\n DepositStoreUtils.set(dataStore, key, deposit);\n }\n\n function removeDeposit(DataStore dataStore, bytes32 key, address account) external {\n DepositStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/test/GlvDepositStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../glv/glvDeposit/GlvDepositStoreUtils.sol\";\n\n/**\n * @title DepositeStoreUtilsTest\n * @dev Contract to help test the DepositStoreUtils library\n */\ncontract GlvDepositStoreUtilsTest {\n function getEmptyGlvDeposit() external pure returns (GlvDeposit.Props memory) {\n GlvDeposit.Props memory glvDeposit;\n return glvDeposit;\n }\n\n function setGlvDeposit(DataStore dataStore, bytes32 key, GlvDeposit.Props memory glvDeposit) external {\n GlvDepositStoreUtils.set(dataStore, key, glvDeposit);\n }\n\n function removeGlvDeposit(DataStore dataStore, bytes32 key, address account) external {\n GlvDepositStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/test/GlvShiftStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../glv/glvShift/GlvShiftStoreUtils.sol\";\n\n/**\n * @title ShifteStoreUtilsTest\n * @dev Contract to help test the ShiftStoreUtils library\n */\ncontract GlvShiftStoreUtilsTest {\n function getEmptyGlvShift() external pure returns (GlvShift.Props memory) {\n GlvShift.Props memory glvShift;\n return glvShift;\n }\n\n function setGlvShift(DataStore dataStore, bytes32 key, GlvShift.Props memory glvShift) external {\n GlvShiftStoreUtils.set(dataStore, key, glvShift);\n }\n\n function removeGlvShift(DataStore dataStore, bytes32 key) external {\n GlvShiftStoreUtils.remove(dataStore, key);\n }\n}\n" + }, + "contracts/test/GlvStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../glv/GlvStoreUtils.sol\";\n\n/**\n * @title GlvStoreUtilsTest\n * @dev Contract to help test the StoreUtils library\n */\ncontract GlvStoreUtilsTest {\n function getEmptyGlv() external pure returns (Glv.Props memory) {\n Glv.Props memory glv;\n return glv;\n }\n\n function setGlv(DataStore dataStore, address key, bytes32 salt, Glv.Props memory glv) external {\n GlvStoreUtils.set(dataStore, key, salt, glv);\n }\n\n function removeGlv(DataStore dataStore, address key) external {\n GlvStoreUtils.remove(dataStore, key);\n }\n}\n" + }, + "contracts/test/GlvWithdrawalStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../glv/glvWithdrawal/GlvWithdrawalStoreUtils.sol\";\n\n/**\n * @title WithdrawaleStoreUtilsTest\n * @dev Contract to help test the WithdrawalStoreUtils library\n */\ncontract GlvWithdrawalStoreUtilsTest {\n function getEmptyGlvWithdrawal() external pure returns (GlvWithdrawal.Props memory) {\n GlvWithdrawal.Props memory glvWithdrawal;\n return glvWithdrawal;\n }\n\n function setGlvWithdrawal(DataStore dataStore, bytes32 key, GlvWithdrawal.Props memory glvWithdrawal) external {\n GlvWithdrawalStoreUtils.set(dataStore, key, glvWithdrawal);\n }\n\n function removeGlvWithdrawal(DataStore dataStore, bytes32 key, address account) external {\n GlvWithdrawalStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/test/MarketStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../market/MarketStoreUtils.sol\";\n\n/**\n * @title MarketStoreUtilsTest\n * @dev Contract to help test the MarketStoreUtils library\n */\ncontract MarketStoreUtilsTest {\n function getEmptyMarket() external pure returns (Market.Props memory) {\n Market.Props memory market;\n return market;\n }\n\n function setMarket(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {\n MarketStoreUtils.set(dataStore, key, salt, market);\n }\n\n function removeMarket(DataStore dataStore, address key, bytes32 salt) external {\n MarketStoreUtils.remove(dataStore, key, salt);\n }\n}\n" + }, + "contracts/test/MarketUtilsTest.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../market/MarketUtils.sol\";\n\ncontract MarketUtilsTest {\n function getUsageFactor(\n DataStore dataStore,\n Market.Props memory market,\n bool isLong,\n uint256 reservedUsd,\n uint256 poolUsd\n ) public view returns (uint256) {\n return MarketUtils.getUsageFactor(dataStore, market, isLong, reservedUsd, poolUsd);\n }\n\n function getPoolUsdWithoutPnl(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n bool isLong,\n bool maximize\n ) public view returns (uint256) {\n return MarketUtils.getPoolUsdWithoutPnl(dataStore, market, prices, isLong, maximize);\n }\n\n function getReservedUsd(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n bool isLong\n ) public view returns (uint256) {\n return MarketUtils.getReservedUsd(dataStore, market, prices, isLong);\n }\n}\n" + }, + "contracts/test/OracleModuleTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../oracle/OracleModule.sol\";\nimport \"../oracle/Oracle.sol\";\nimport \"../oracle/GmOracleUtils.sol\";\nimport \"../utils/Uint256Mask.sol\";\nimport \"../chain/Chain.sol\";\n\n/**\n * @title OracleModuleTest\n * @dev Contract to help test the OracleModule contract\n */\ncontract OracleModuleTest is OracleModule {\n using Uint256Mask for Uint256Mask.Mask;\n\n constructor(Oracle _oracle) OracleModule(_oracle) {}\n\n function withOraclePricesTest(\n OracleUtils.SetPricesParams memory oracleParams\n ) external withOraclePrices(oracleParams) {\n }\n\n function getTokenOracleType(DataStore dataStore, address token) external view returns (bytes32) {\n return dataStore.getBytes32(Keys.oracleTypeKey(token));\n }\n\n function validateSignerWithSalt(\n DataStore dataStore,\n bytes32 SALT,\n GmOracleUtils.Report memory report,\n address token,\n uint256 minPrice,\n uint256 maxPrice,\n bytes memory signature,\n address expectedSigner\n ) external view {\n bytes32 tokenOracleType = dataStore.getBytes32(Keys.oracleTypeKey(token));\n\n GmOracleUtils.validateSigner(\n SALT,\n report,\n token,\n minPrice,\n maxPrice,\n tokenOracleType,\n signature,\n expectedSigner\n );\n }\n\n function validateSigner(\n DataStore dataStore,\n GmOracleUtils.Report memory report,\n address token,\n uint256 minPrice,\n uint256 maxPrice,\n bytes memory signature,\n address expectedSigner\n ) external view {\n bytes32 tokenOracleType = dataStore.getBytes32(Keys.oracleTypeKey(token));\n\n GmOracleUtils.validateSigner(\n getSalt(),\n report,\n token,\n minPrice,\n maxPrice,\n tokenOracleType,\n signature,\n expectedSigner\n );\n }\n\n function getSalt() public view returns (bytes32) {\n return keccak256(abi.encode(block.chainid, \"xget-oracle-v1\"));\n }\n}\n" + }, + "contracts/test/OrderStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../order/OrderStoreUtils.sol\";\n\n/**\n * @title OrderStoreUtilsTest\n * @dev Contract to help test the OrderStoreUtils library\n */\ncontract OrderStoreUtilsTest {\n function getEmptyOrder() external pure returns (Order.Props memory) {\n Order.Props memory order;\n return order;\n }\n\n function setOrder(DataStore dataStore, bytes32 key, Order.Props memory order) external {\n OrderStoreUtils.set(dataStore, key, order);\n }\n\n function removeOrder(DataStore dataStore, bytes32 key, address account) external {\n OrderStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/test/PositionStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../position/PositionStoreUtils.sol\";\n\n/**\n * @title PositionStoreUtilsTest\n * @dev Contract to help test the PositionStoreUtils library\n */\ncontract PositionStoreUtilsTest {\n function getEmptyPosition() external pure returns (Position.Props memory) {\n Position.Props memory position;\n return position;\n }\n\n function setPosition(DataStore dataStore, bytes32 key, Position.Props memory position) external {\n PositionStoreUtils.set(dataStore, key, position);\n }\n\n function removePosition(DataStore dataStore, bytes32 key, address account) external {\n PositionStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/test/ShiftStoreUtilsTest.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../shift/ShiftStoreUtils.sol\";\n\ncontract ShiftStoreUtilsTest {\n function getEmptyShift() external pure returns (Shift.Props memory) {\n Shift.Props memory shift;\n return shift;\n }\n\n function setShift(DataStore dataStore, bytes32 key, Shift.Props memory shift) external {\n ShiftStoreUtils.set(dataStore, key, shift);\n }\n\n function removeShift(DataStore dataStore, bytes32 key, address account) external {\n ShiftStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/test/WithdrawalStoreUtilsTest.sol": { + "content": "\n// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../withdrawal/WithdrawalStoreUtils.sol\";\n\n/**\n * @title WithdrawalStoreUtilsTest\n * @dev Contract to help test the WithdrawalStoreUtils library\n */\ncontract WithdrawalStoreUtilsTest {\n function getEmptyWithdrawal() external pure returns (Withdrawal.Props memory) {\n Withdrawal.Props memory withdrawal;\n return withdrawal;\n }\n\n function setWithdrawal(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) external {\n WithdrawalStoreUtils.set(dataStore, key, withdrawal);\n }\n\n function removeWithdrawal(DataStore dataStore, bytes32 key, address account) external {\n WithdrawalStoreUtils.remove(dataStore, key, account);\n }\n}\n" + }, + "contracts/token/IWNT.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n/**\n * @title IWNT\n * @dev Interface for Wrapped Native Tokens, e.g. WETH\n * The contract is named WNT instead of WETH for a more general reference name\n * that can be used on any blockchain\n */\ninterface IWNT {\n function deposit() external payable;\n function withdraw(uint256 amount) external;\n}\n" + }, + "contracts/token/TokenUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../data/DataStore.sol\";\nimport \"../data/Keys.sol\";\nimport \"../error/ErrorUtils.sol\";\nimport \"../utils/AccountUtils.sol\";\n\nimport \"./IWNT.sol\";\n\n/**\n * @title TokenUtils\n * @dev Library for token functions, helps with transferring of tokens and\n * native token functions\n */\nlibrary TokenUtils {\n using Address for address;\n using SafeERC20 for IERC20;\n\n event TokenTransferReverted(string reason, bytes returndata);\n event NativeTokenTransferReverted(string reason);\n\n /**\n * @dev Returns the address of the WNT token.\n * @param dataStore DataStore contract instance where the address of the WNT token is stored.\n * @return The address of the WNT token.\n */\n function wnt(DataStore dataStore) internal view returns (address) {\n return dataStore.getAddress(Keys.WNT);\n }\n\n /**\n * @dev Transfers the specified amount of `token` from the caller to `receiver`.\n * limit the amount of gas forwarded so that a user cannot intentionally\n * construct a token call that would consume all gas and prevent necessary\n * actions like request cancellation from being executed\n *\n * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.\n * @param token The address of the ERC20 token that is being transferred.\n * @param receiver The address of the recipient of the `token` transfer.\n * @param amount The amount of `token` to transfer.\n */\n function transfer(\n DataStore dataStore,\n address token,\n address receiver,\n uint256 amount\n ) internal {\n if (amount == 0) { return; }\n AccountUtils.validateReceiver(receiver);\n\n uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));\n if (gasLimit == 0) {\n revert Errors.EmptyTokenTranferGasLimit(token);\n }\n\n (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(\n IERC20(token),\n receiver,\n amount,\n gasLimit\n );\n\n if (success0) { return; }\n\n address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);\n\n if (holdingAddress == address(0)) {\n revert Errors.EmptyHoldingAddress();\n }\n\n // in case transfers to the receiver fail due to blacklisting or other reasons\n // send the tokens to a holding address to avoid possible gaming through reverting\n // transfers\n (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(\n IERC20(token),\n holdingAddress,\n amount,\n gasLimit\n );\n\n if (success1) { return; }\n\n (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);\n emit TokenTransferReverted(reason, returndata);\n\n // throw custom errors to prevent spoofing of errors\n // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler\n // do not cancel requests for specific errors\n revert Errors.TokenTransferError(token, receiver, amount);\n }\n\n function sendNativeToken(\n DataStore dataStore,\n address receiver,\n uint256 amount\n ) internal {\n if (amount == 0) { return; }\n\n AccountUtils.validateReceiver(receiver);\n\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\n\n bool success;\n // use an assembly call to avoid loading large data into memory\n // input mem[in…(in+insize)]\n // output area mem[out…(out+outsize))]\n assembly {\n success := call(\n gasLimit, // gas limit\n receiver, // receiver\n amount, // value\n 0, // in\n 0, // insize\n 0, // out\n 0 // outsize\n )\n }\n\n if (success) { return; }\n\n // if the transfer failed, re-wrap the token and send it to the receiver\n depositAndSendWrappedNativeToken(\n dataStore,\n receiver,\n amount\n );\n }\n\n /**\n * Deposits the specified amount of native token and sends the specified\n * amount of wrapped native token to the specified receiver address.\n *\n * @param dataStore the data store to use for storing and retrieving data\n * @param receiver the address of the recipient of the wrapped native token transfer\n * @param amount the amount of native token to deposit and the amount of wrapped native token to send\n */\n function depositAndSendWrappedNativeToken(\n DataStore dataStore,\n address receiver,\n uint256 amount\n ) internal {\n if (amount == 0) { return; }\n AccountUtils.validateReceiver(receiver);\n\n address _wnt = wnt(dataStore);\n IWNT(_wnt).deposit{value: amount}();\n\n transfer(\n dataStore,\n _wnt,\n receiver,\n amount\n );\n }\n\n /**\n * @dev Withdraws the specified amount of wrapped native token and sends the\n * corresponding amount of native token to the specified receiver address.\n *\n * limit the amount of gas forwarded so that a user cannot intentionally\n * construct a token call that would consume all gas and prevent necessary\n * actions like request cancellation from being executed\n *\n * @param dataStore the data store to use for storing and retrieving data\n * @param _wnt the address of the WNT contract to withdraw the wrapped native token from\n * @param receiver the address of the recipient of the native token transfer\n * @param amount the amount of wrapped native token to withdraw and the amount of native token to send\n */\n function withdrawAndSendNativeToken(\n DataStore dataStore,\n address _wnt,\n address receiver,\n uint256 amount\n ) internal {\n if (amount == 0) { return; }\n AccountUtils.validateReceiver(receiver);\n\n IWNT(_wnt).withdraw(amount);\n\n uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);\n\n bool success;\n // use an assembly call to avoid loading large data into memory\n // input mem[in…(in+insize)]\n // output area mem[out…(out+outsize))]\n assembly {\n success := call(\n gasLimit, // gas limit\n receiver, // receiver\n amount, // value\n 0, // in\n 0, // insize\n 0, // out\n 0 // outsize\n )\n }\n\n if (success) { return; }\n\n // if the transfer failed, re-wrap the token and send it to the receiver\n depositAndSendWrappedNativeToken(\n dataStore,\n receiver,\n amount\n );\n }\n\n /**\n * @dev Transfers the specified amount of ERC20 token to the specified receiver\n * address, with a gas limit to prevent the transfer from consuming all available gas.\n * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol\n *\n * @param token the ERC20 contract to transfer the tokens from\n * @param to the address of the recipient of the token transfer\n * @param amount the amount of tokens to transfer\n * @param gasLimit the maximum amount of gas that the token transfer can consume\n * @return a tuple containing a boolean indicating the success or failure of the\n * token transfer, and a bytes value containing the return data from the token transfer\n */\n function nonRevertingTransferWithGasLimit(\n IERC20 token,\n address to,\n uint256 amount,\n uint256 gasLimit\n ) internal returns (bool, bytes memory) {\n bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);\n (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);\n\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (!address(token).isContract()) {\n return (false, \"Call to non-contract\");\n }\n }\n\n // some tokens do not revert on a failed transfer, they will return a boolean instead\n // validate that the returned boolean is true, otherwise indicate that the token transfer failed\n if (returndata.length > 0 && !abi.decode(returndata, (bool))) {\n return (false, returndata);\n }\n\n // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails\n // for these tokens, if success is true then the transfer should have completed\n return (true, returndata);\n }\n\n return (false, returndata);\n }\n}\n" + }, + "contracts/utils/AccountUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/Errors.sol\";\n\nlibrary AccountUtils {\n function validateAccount(address account) internal pure {\n if (account == address(0)) {\n revert Errors.EmptyAccount();\n }\n }\n\n function validateReceiver(address receiver) internal pure {\n if (receiver == address(0)) {\n revert Errors.EmptyReceiver();\n }\n }\n\n function isContract(address account) internal view returns (bool) {\n return account.code.length > 0;\n }\n\n}\n" + }, + "contracts/utils/Array.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"../error/Errors.sol\";\n\n/**\n * @title Array\n * @dev Library for array functions\n */\nlibrary Array {\n using SafeCast for int256;\n\n /**\n * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.\n *\n * @param arr the array to get the value from\n * @param index the index of the element in the array\n * @return the value of the element at the specified index in the array\n */\n function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {\n if (index < arr.length) {\n return arr[index];\n }\n\n return bytes32(0);\n }\n\n /**\n * @dev Determines whether all of the elements in the given array are equal to the specified value.\n *\n * @param arr the array to check the elements of\n * @param value the value to compare the elements of the array to\n * @return true if all of the elements in the array are equal to the specified value, false otherwise\n */\n function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\n for (uint256 i; i < arr.length; i++) {\n if (arr[i] != value) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @dev Determines whether all of the elements in the given array are greater than the specified value.\n *\n * @param arr the array to check the elements of\n * @param value the value to compare the elements of the array to\n * @return true if all of the elements in the array are greater than the specified value, false otherwise\n */\n function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\n for (uint256 i; i < arr.length; i++) {\n if (arr[i] <= value) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.\n *\n * @param arr the array to check the elements of\n * @param value the value to compare the elements of the array to\n * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise\n */\n function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\n for (uint256 i; i < arr.length; i++) {\n if (arr[i] < value) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @dev Determines whether all of the elements in the given array are less than the specified value.\n *\n * @param arr the array to check the elements of\n * @param value the value to compare the elements of the array to\n * @return true if all of the elements in the array are less than the specified value, false otherwise\n */\n function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {\n for (uint256 i; i < arr.length; i++) {\n if (arr[i] >= value) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.\n *\n * @param arr the array to check the elements of\n * @param value the value to compare the elements of the array to\n * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise\n */\n function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {\n for (uint256 i; i < arr.length; i++) {\n if (arr[i] > value) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.\n *\n * @param arr the array to get the median value from\n * @return the median value of the elements in the given array\n */\n function getMedian(uint256[] memory arr) internal pure returns (uint256) {\n if (arr.length % 2 == 1) {\n return arr[arr.length / 2];\n }\n\n return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;\n }\n\n /**\n * @dev Gets the uncompacted value at the specified index in the given array of compacted values.\n *\n * @param compactedValues the array of compacted values to get the uncompacted value from\n * @param index the index of the uncompacted value in the array\n * @param compactedValueBitLength the length of each compacted value, in bits\n * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value\n * @return the uncompacted value at the specified index in the array of compacted values\n */\n function getUncompactedValue(\n uint256[] memory compactedValues,\n uint256 index,\n uint256 compactedValueBitLength,\n uint256 bitmask,\n string memory label\n ) internal pure returns (uint256) {\n uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;\n\n uint256 slotIndex = index / compactedValuesPerSlot;\n if (slotIndex >= compactedValues.length) {\n revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);\n }\n\n uint256 slotBits = compactedValues[slotIndex];\n uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;\n\n uint256 value = (slotBits >> offset) & bitmask;\n\n return value;\n }\n\n /**\n * Converts an array of bytes32 values to bytes.\n * \n * @dev Used to decode the dataList and the first element is not included in the result (i.e. loop starts at index 1)\n * because it is expected to be the GMX_DATA_ACTION hash.\n *\n * @param dataList the array of bytes32 values to convert\n * @return data the bytes array representing the input dataList\n */\n function dataArrayToBytes(bytes32[] memory dataList) internal pure returns (bytes memory) {\n bytes memory data;\n\n for (uint256 i = 1; i < dataList.length; i++) {\n data = bytes.concat(data, bytes32(dataList[i]));\n }\n\n return data;\n }\n}\n" + }, + "contracts/utils/BasicMulticall.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/ErrorUtils.sol\";\n\n/**\n * @title BasicMulticall\n */\nabstract contract BasicMulticall {\n /**\n * @dev Receives and executes a batch of function calls on this contract.\n */\n function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {\n results = new bytes[](data.length);\n\n for (uint256 i; i < data.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n if (!success) {\n ErrorUtils.revertWithParsedMessage(result);\n }\n\n results[i] = result;\n }\n\n return results;\n }\n}\n" + }, + "contracts/utils/Bits.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n/**\n * @title Bits\n * @dev Library for bit values\n */\nlibrary Bits {\n // @dev uint256(~0) is 256 bits of 1s\n // @dev shift the 1s by (256 - 8) to get (256 - 8) 0s followed by 8 1s\n uint256 constant public BITMASK_8 = ~uint256(0) >> (256 - 8);\n // @dev shift the 1s by (256 - 16) to get (256 - 16) 0s followed by 16 1s\n uint256 constant public BITMASK_16 = ~uint256(0) >> (256 - 16);\n // @dev shift the 1s by (256 - 32) to get (256 - 32) 0s followed by 32 1s\n uint256 constant public BITMASK_32 = ~uint256(0) >> (256 - 32);\n // @dev shift the 1s by (256 - 64) to get (256 - 64) 0s followed by 64 1s\n uint256 constant public BITMASK_64 = ~uint256(0) >> (256 - 64);\n}\n" + }, + "contracts/utils/Calc.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\n/**\n * @title Calc\n * @dev Library for math functions\n */\nlibrary Calc {\n using SignedMath for int256;\n using SafeCast for uint256;\n\n // this method assumes that min is less than max\n function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {\n uint256 magnitude = value.abs();\n\n if (magnitude < min) {\n magnitude = min;\n }\n\n if (magnitude > max) {\n magnitude = max;\n }\n\n int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();\n\n return magnitude.toInt256() * sign;\n }\n\n /**\n * @dev Calculates the result of dividing the first number by the second number,\n * rounded up to the nearest integer.\n *\n * @param a the dividend\n * @param b the divisor\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\n */\n function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {\n return (a + b - 1) / b;\n }\n\n /**\n * Calculates the result of dividing the first number by the second number,\n * rounded up to the nearest integer.\n * The rounding is purely on the magnitude of a, if a is negative the result\n * is a larger magnitude negative\n *\n * @param a the dividend\n * @param b the divisor\n * @return the result of dividing the first number by the second number, rounded up to the nearest integer\n */\n function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {\n if (a < 0) {\n return (a - b.toInt256() + 1) / b.toInt256();\n }\n\n return (a + b.toInt256() - 1) / b.toInt256();\n }\n\n /**\n * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.\n *\n * @param a the first number\n * @param b the second number\n * @return the result of adding the two numbers together\n */\n function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {\n if (b > 0) {\n return a + b.abs();\n }\n\n return a - b.abs();\n }\n\n /**\n * Adds two numbers together and return an int256 value, treating the second number as a signed integer.\n *\n * @param a the first number\n * @param b the second number\n * @return the result of adding the two numbers together\n */\n function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {\n return a.toInt256() + b;\n }\n\n /**\n * @dev Calculates the absolute difference between two numbers.\n *\n * @param a the first number\n * @param b the second number\n * @return the absolute difference between the two numbers\n */\n function diff(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n /**\n * Adds two numbers together, the result is bounded to prevent overflows.\n *\n * @param a the first number\n * @param b the second number\n * @return the result of adding the two numbers together\n */\n function boundedAdd(int256 a, int256 b) internal pure returns (int256) {\n // if either a or b is zero or if the signs are different there should not be any overflows\n if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {\n return a + b;\n }\n\n // if adding `b` to `a` would result in a value less than the min int256 value\n // then return the min int256 value\n if (a < 0 && b <= type(int256).min - a) {\n return type(int256).min;\n }\n\n // if adding `b` to `a` would result in a value more than the max int256 value\n // then return the max int256 value\n if (a > 0 && b >= type(int256).max - a) {\n return type(int256).max;\n }\n\n return a + b;\n }\n\n /**\n * Returns a - b, the result is bounded to prevent overflows.\n * Note that this will revert if b is type(int256).min because of the usage of \"-b\".\n *\n * @param a the first number\n * @param b the second number\n * @return the bounded result of a - b\n */\n function boundedSub(int256 a, int256 b) internal pure returns (int256) {\n // if either a or b is zero or the signs are the same there should not be any overflow\n if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {\n return a - b;\n }\n\n // if adding `-b` to `a` would result in a value greater than the max int256 value\n // then return the max int256 value\n if (a > 0 && -b >= type(int256).max - a) {\n return type(int256).max;\n }\n\n // if subtracting `b` from `a` would result in a value less than the min int256 value\n // then return the min int256 value\n if (a < 0 && -b <= type(int256).min - a) {\n return type(int256).min;\n }\n\n return a - b;\n }\n\n\n /**\n * Converts the given unsigned integer to a signed integer, using the given\n * flag to determine whether the result should be positive or negative.\n *\n * @param a the unsigned integer to convert\n * @param isPositive whether the result should be positive (if true) or negative (if false)\n * @return the signed integer representation of the given unsigned integer\n */\n function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {\n if (isPositive) {\n return a.toInt256();\n } else {\n return -a.toInt256();\n }\n }\n}\n" + }, + "contracts/utils/Cast.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/Errors.sol\";\n\n/**\n * @title Cast\n * @dev Library for casting functions\n */\nlibrary Cast {\n function toBytes32(address value) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(value)));\n }\n\n /**\n * @dev Converts a bytes array to a uint256.\n * Handles cases where the uint256 stored in bytes is stored with or without padding.\n * @param uint256AsBytes The bytes array representing the uint256 value.\n * @return value The uint256 value obtained from the bytes array.\n */\n function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {\n uint256 length = uint256AsBytes.length;\n\n if(length > 32) {\n revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);\n }\n\n if (length == 0) {\n return 0;\n }\n\n uint256 value;\n\n assembly {\n value := mload(add(uint256AsBytes, 32))\n }\n\n return value = value >> (8 * (32 - length));\n }\n\n function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {\n b = new bytes(32);\n assembly { mstore(add(b, 32), x) }\n return b;\n }\n\n function uint192ToBytes(uint192 x) internal pure returns (bytes memory b) {\n b = new bytes(32);\n assembly { mstore(add(b, 32), x) }\n return b;\n }\n\n function uint32ToBytes(uint32 x) internal pure returns (bytes memory b) {\n b = new bytes(32);\n assembly { mstore(add(b, 32), x) }\n return b;\n }\n\n function int32ToBytes(int32 x) internal pure returns (bytes memory b) {\n b = new bytes(32);\n// bytes memory expoBytes = new bytes(1);\n// if (x < 0) {\n// expoBytes[0] = bytes1(uint8(-x)); // Use absolute value, e.g., uint8(8) -> 0x08\n// } else {\n// expoBytes[0] = bytes1(uint8(x));\n// }\n assembly { mstore(add(b, 32), x) }\n return b;\n// return expoBytes;\n }\n}\n" + }, + "contracts/utils/EnumerableValues.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\n/**\n * @title EnumerableValues\n * @dev Library to extend the EnumerableSet library with functions to get\n * valuesAt for a range\n */\nlibrary EnumerableValues {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableSet for EnumerableSet.UintSet;\n\n /**\n * Returns an array of bytes32 values from the given set, starting at the given\n * start index and ending before the given end index.\n *\n * @param set The set to get the values from.\n * @param start The starting index.\n * @param end The ending index.\n * @return An array of bytes32 values.\n */\n function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n uint256 max = set.length();\n if (end > max) { end = max; }\n\n bytes32[] memory items = new bytes32[](end - start);\n for (uint256 i = start; i < end; i++) {\n items[i - start] = set.at(i);\n }\n\n return items;\n }\n\n\n /**\n * Returns an array of address values from the given set, starting at the given\n * start index and ending before the given end index.\n *\n * @param set The set to get the values from.\n * @param start The starting index.\n * @param end The ending index.\n * @return An array of address values.\n */\n function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\n uint256 max = set.length();\n if (end > max) { end = max; }\n\n address[] memory items = new address[](end - start);\n for (uint256 i = start; i < end; i++) {\n items[i - start] = set.at(i);\n }\n\n return items;\n }\n\n\n /**\n * Returns an array of uint256 values from the given set, starting at the given\n * start index and ending before the given end index, the item at the end index will not be returned.\n *\n * @param set The set to get the values from.\n * @param start The starting index (inclusive, item at the start index will be returned).\n * @param end The ending index (exclusive, item at the end index will not be returned).\n * @return An array of uint256 values.\n */\n function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\n if (start >= set.length()) {\n return new uint256[](0);\n }\n\n uint256 max = set.length();\n if (end > max) { end = max; }\n\n uint256[] memory items = new uint256[](end - start);\n for (uint256 i = start; i < end; i++) {\n items[i - start] = set.at(i);\n }\n\n return items;\n }\n}\n" + }, + "contracts/utils/GlobalReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nabstract contract GlobalReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n uint256 private constant NOT_ENTERED = 0;\n uint256 private constant ENTERED = 1;\n\n DataStore public immutable dataStore;\n\n constructor(DataStore _dataStore) {\n dataStore = _dataStore;\n }\n\n modifier globalNonReentrant() {\n _globalNonReentrantBefore();\n _;\n _globalNonReentrantAfter();\n }\n\n function _globalNonReentrantBefore() private {\n uint256 status = dataStore.getUint(Keys.REENTRANCY_GUARD_STATUS);\n\n require(status == NOT_ENTERED, \"ReentrancyGuard: reentrant call\");\n\n dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, ENTERED);\n }\n\n function _globalNonReentrantAfter() private {\n dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, NOT_ENTERED);\n }\n}\n" + }, + "contracts/utils/PayableMulticall.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/ErrorUtils.sol\";\n\n/**\n * @title PayableMulticall\n * @dev Contract to help call multiple functions in a single transaction\n * all function calls will have the original sender as the msg.sender value\n * IMPORTANT: in the multicall, msg.value will be the same for each delegatecall\n * extra care should be taken if msg.value is used in any of the functions of the inheriting contract\n */\nabstract contract PayableMulticall {\n /**\n * @dev Receives and executes a batch of function calls on this contract.\n */\n function multicall(bytes[] calldata data) external payable virtual returns (bytes[] memory results) {\n results = new bytes[](data.length);\n\n for (uint256 i; i < data.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n if (!success) {\n ErrorUtils.revertWithParsedMessage(result);\n }\n\n results[i] = result;\n }\n\n return results;\n }\n}\n" + }, + "contracts/utils/Precision.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n// there is a known issue with prb-math v3.x releases\n// https://github.com/PaulRBerg/prb-math/issues/178\n// due to this, either prb-math v2.x or v4.x versions should be used instead\nimport \"prb-math/contracts/PRBMathUD60x18.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n/**\n * @title Precision\n * @dev Library for precision values and conversions\n */\nlibrary Precision {\n using SafeCast for uint256;\n using SafeCast for int256;\n using SignedMath for int256;\n\n uint256 public constant FLOAT_PRECISION = 10 ** 30;\n uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;\n\n uint256 public constant WEI_PRECISION = 10 ** 18;\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\n\n uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;\n\n /**\n * Applies the given factor to the given value and returns the result.\n *\n * @param value The value to apply the factor to.\n * @param factor The factor to apply.\n * @return The result of applying the factor to the value.\n */\n function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {\n return mulDiv(value, factor, FLOAT_PRECISION);\n }\n\n /**\n * Applies the given factor to the given value and returns the result.\n *\n * @param value The value to apply the factor to.\n * @param factor The factor to apply.\n * @return The result of applying the factor to the value.\n */\n function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {\n return mulDiv(value, factor, FLOAT_PRECISION);\n }\n\n function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {\n return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);\n }\n\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {\n return Math.mulDiv(value, numerator, denominator);\n }\n\n function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {\n return mulDiv(numerator, value, denominator);\n }\n\n function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {\n uint256 result = mulDiv(value, numerator.abs(), denominator);\n return numerator > 0 ? result.toInt256() : -result.toInt256();\n }\n\n function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\n uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);\n return numerator > 0 ? result.toInt256() : -result.toInt256();\n }\n\n function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {\n if (roundUpMagnitude) {\n return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);\n }\n\n return Math.mulDiv(value, numerator, denominator);\n }\n\n function mulDiv(int256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {\n uint256 result = mulDiv(value.abs(), numerator, denominator, roundUpMagnitude);\n return value > 0 ? result.toInt256() : -result.toInt256();\n }\n\n function applyExponentFactor(\n uint256 floatValue,\n uint256 exponentFactor\n ) internal pure returns (uint256) {\n // `PRBMathUD60x18.pow` doesn't work for `x` less than one\n if (floatValue < FLOAT_PRECISION) {\n return 0;\n }\n\n if (exponentFactor == FLOAT_PRECISION) {\n return floatValue;\n }\n\n // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18\n // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals\n uint256 weiValue = PRBMathUD60x18.pow(\n floatToWei(floatValue),\n floatToWei(exponentFactor)\n );\n\n return weiToFloat(weiValue);\n }\n\n function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {\n if (value == 0) { return 0; }\n\n if (roundUpMagnitude) {\n return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);\n }\n\n return Math.mulDiv(value, FLOAT_PRECISION, divisor);\n }\n\n function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {\n return toFactor(value, divisor, false);\n }\n\n function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {\n uint256 result = toFactor(value.abs(), divisor);\n return value > 0 ? result.toInt256() : -result.toInt256();\n }\n\n /**\n * Converts the given value from float to wei.\n *\n * @param value The value to convert.\n * @return The converted value in wei.\n */\n function floatToWei(uint256 value) internal pure returns (uint256) {\n return value / FLOAT_TO_WEI_DIVISOR;\n }\n\n /**\n * Converts the given value from wei to float.\n *\n * @param value The value to convert.\n * @return The converted value in float.\n */\n function weiToFloat(uint256 value) internal pure returns (uint256) {\n return value * FLOAT_TO_WEI_DIVISOR;\n }\n\n /**\n * Converts the given number of basis points to float.\n *\n * @param basisPoints The number of basis points to convert.\n * @return The converted value in float.\n */\n function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {\n return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;\n }\n}\n" + }, + "contracts/utils/StringUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nlibrary StringUtils {\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/utils/Uint256Mask.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../error/Errors.sol\";\n\nlibrary Uint256Mask {\n struct Mask {\n uint256 bits;\n }\n\n function validateUniqueAndSetIndex(\n Mask memory mask,\n uint256 index,\n string memory label\n ) internal pure {\n if (index >= 256) {\n revert Errors.MaskIndexOutOfBounds(index, label);\n }\n\n uint256 bit = 1 << index;\n\n if (mask.bits & bit != 0) {\n revert Errors.DuplicatedIndex(index, label);\n }\n\n mask.bits = mask.bits | bit;\n }\n}\n" + }, + "contracts/v1/IMintable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IMintable {\n function mint(address _account, uint256 _amount) external;\n}\n" + }, + "contracts/v1/IRewardDistributorV1.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IRewardDistributor {\n function updateLastDistributionTime() external;\n function setTokensPerInterval(uint256 _amount) external;\n}\n" + }, + "contracts/v1/IRewardTrackerV1.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IRewardTracker {\n function distributor() external view returns (address);\n\n function updateRewards() external;\n}\n" + }, + "contracts/v1/IRouterV1.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IRouterV1 {\n function swap(address[] memory _path, uint256 _amountIn, uint256 _minOut, address _receiver) external;\n}\n" + }, + "contracts/v1/IVaultGovV1.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IVaultGovV1 {\n function withdrawFees(address _vault, address _token, address _receiver) external;\n}\n" + }, + "contracts/v1/IVaultV1.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IVaultV1 {\n function allWhitelistedTokensLength() external view returns (uint256);\n function allWhitelistedTokens(uint256) external view returns (address);\n function gov() external view returns (address);\n function feeReserves(address feeToken) external view returns (uint256);\n function withdrawFees(address _token, address _receiver) external returns (uint256);\n function getMaxPrice(address _token) external returns (uint256);\n}\n" + }, + "contracts/v1/IVesterV1.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IVester {\n function bonusRewards(address _account) external view returns (uint256);\n function setBonusRewards(address _account, uint256 _amount) external;\n}" + }, + "contracts/withdrawal/ExecuteWithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\n\nimport \"../multichain/MultichainUtils.sol\";\n\nimport \"./IExecuteWithdrawalUtils.sol\";\nimport \"./WithdrawalVault.sol\";\nimport \"./WithdrawalStoreUtils.sol\";\nimport \"./WithdrawalEventUtils.sol\";\n\nimport \"../pricing/SwapPricingUtils.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../position/PositionUtils.sol\";\nimport \"../fee/FeeUtils.sol\";\nimport \"../swap/SwapUtils.sol\";\n\nimport \"../multichain/BridgeOutFromControllerUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\n\nimport \"../utils/Array.sol\";\n\nlibrary ExecuteWithdrawalUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n using Array for uint256[];\n using Price for Price.Props;\n using Withdrawal for Withdrawal.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n struct ExecuteWithdrawalCache {\n uint256 requestExpirationTime;\n uint256 maxOracleTimestamp;\n uint256 marketTokensBalance;\n uint256 oraclePriceCount;\n Market.Props market;\n MarketUtils.MarketPrices prices;\n IExecuteWithdrawalUtils.ExecuteWithdrawalResult result;\n }\n\n struct _ExecuteWithdrawalCache {\n uint256 longTokenOutputAmount;\n uint256 shortTokenOutputAmount;\n SwapPricingUtils.SwapFees longTokenFees;\n SwapPricingUtils.SwapFees shortTokenFees;\n uint256 longTokenPoolAmountDelta;\n uint256 shortTokenPoolAmountDelta;\n }\n\n struct SwapCache {\n Market.Props[] swapPathMarkets;\n ISwapUtils.SwapParams swapParams;\n address outputToken;\n uint256 outputAmount;\n }\n\n /**\n * Executes a withdrawal on the market.\n *\n * @param params The parameters for executing the withdrawal.\n */\n function executeWithdrawal(\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params,\n Withdrawal.Props memory withdrawal\n ) external returns (IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory) {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n params.startingGas -= gasleft() / 63;\n\n WithdrawalStoreUtils.remove(params.dataStore, params.key, withdrawal.account());\n\n if (withdrawal.account() == address(0)) {\n revert Errors.EmptyWithdrawal();\n }\n if (withdrawal.marketTokenAmount() == 0) {\n revert Errors.EmptyWithdrawalAmount();\n }\n\n if (params.oracle.minTimestamp() < withdrawal.updatedAtTime()) {\n revert Errors.OracleTimestampsAreSmallerThanRequired(\n params.oracle.minTimestamp(),\n withdrawal.updatedAtTime()\n );\n }\n\n ExecuteWithdrawalCache memory cache;\n\n cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);\n cache.maxOracleTimestamp = params.oracle.maxTimestamp();\n\n if (cache.maxOracleTimestamp > withdrawal.updatedAtTime() + cache.requestExpirationTime) {\n revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(\n cache.maxOracleTimestamp,\n withdrawal.updatedAtTime(),\n cache.requestExpirationTime\n );\n }\n\n MarketUtils.distributePositionImpactPool(params.dataStore, params.eventEmitter, withdrawal.market());\n\n cache.market = MarketUtils.getEnabledMarket(params.dataStore, withdrawal.market());\n cache.prices = MarketUtils.getMarketPrices(params.oracle, cache.market);\n\n PositionUtils.updateFundingAndBorrowingState(params.dataStore, params.eventEmitter, cache.market, cache.prices);\n\n cache.marketTokensBalance = MarketToken(payable(withdrawal.market())).balanceOf(\n address(params.withdrawalVault)\n );\n if (cache.marketTokensBalance < withdrawal.marketTokenAmount()) {\n revert Errors.InsufficientMarketTokens(cache.marketTokensBalance, withdrawal.marketTokenAmount());\n }\n\n cache.result = _executeWithdrawal(params, withdrawal, cache.market, cache.prices);\n\n WithdrawalEventUtils.emitWithdrawalExecuted(\n params.eventEmitter,\n params.key,\n withdrawal.account(),\n params.swapPricingType\n );\n\n EventUtils.EventLogData memory eventData;\n eventData.addressItems.initItems(2);\n eventData.addressItems.setItem(0, \"outputToken\", cache.result.outputToken);\n eventData.addressItems.setItem(1, \"secondaryOutputToken\", cache.result.secondaryOutputToken);\n eventData.uintItems.initItems(2);\n eventData.uintItems.setItem(0, \"outputAmount\", cache.result.outputAmount);\n eventData.uintItems.setItem(1, \"secondaryOutputAmount\", cache.result.secondaryOutputAmount);\n CallbackUtils.afterWithdrawalExecution(params.key, withdrawal, eventData);\n\n BridgeOutFromControllerUtils.bridgeOutFromController(\n params.eventEmitter,\n params.multichainTransferRouter,\n BridgeOutFromControllerUtils.BridgeOutFromControllerParams({\n account: withdrawal.account(), // account\n receiver: withdrawal.receiver(), // receiver\n srcChainId: withdrawal.srcChainId(),\n token: cache.result.outputToken, // token\n amount: cache.result.outputAmount, // amount\n secondaryToken: cache.result.secondaryOutputToken, // secondaryToken\n secondaryAmount: cache.result.secondaryOutputAmount, // secondaryAmount\n dataList: withdrawal.dataList()\n })\n );\n\n cache.oraclePriceCount = GasUtils.estimateWithdrawalOraclePriceCount(\n withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length\n );\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n params.dataStore,\n params.eventEmitter,\n params.multichainVault,\n params.withdrawalVault\n ),\n params.key,\n withdrawal.callbackContract(),\n withdrawal.executionFee(),\n params.startingGas,\n cache.oraclePriceCount,\n params.keeper,\n withdrawal.receiver(),\n withdrawal.srcChainId()\n );\n\n return cache.result;\n }\n\n /**\n * @dev executes a withdrawal.\n * @param params ExecuteWithdrawalParams.\n * @param withdrawal The withdrawal to execute.\n */\n function _executeWithdrawal(\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params,\n Withdrawal.Props memory withdrawal,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices\n ) internal returns (IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory) {\n _ExecuteWithdrawalCache memory cache;\n\n (cache.longTokenOutputAmount, cache.shortTokenOutputAmount) = _getOutputAmounts(\n params,\n market,\n prices,\n withdrawal.marketTokenAmount()\n );\n\n cache.longTokenFees = SwapPricingUtils.getSwapFees(\n params.dataStore,\n market.marketToken,\n cache.longTokenOutputAmount,\n false, // balanceWasImproved\n withdrawal.uiFeeReceiver(),\n params.swapPricingType\n );\n\n FeeUtils.incrementClaimableFeeAmount(\n params.dataStore,\n params.eventEmitter,\n market.marketToken,\n market.longToken,\n cache.longTokenFees.feeReceiverAmount,\n Keys.WITHDRAWAL_FEE_TYPE\n );\n\n FeeUtils.incrementClaimableUiFeeAmount(\n params.dataStore,\n params.eventEmitter,\n withdrawal.uiFeeReceiver(),\n market.marketToken,\n market.longToken,\n cache.longTokenFees.uiFeeAmount,\n Keys.UI_WITHDRAWAL_FEE_TYPE\n );\n\n cache.shortTokenFees = SwapPricingUtils.getSwapFees(\n params.dataStore,\n market.marketToken,\n cache.shortTokenOutputAmount,\n false, // balanceWasImproved\n withdrawal.uiFeeReceiver(),\n params.swapPricingType\n );\n\n FeeUtils.incrementClaimableFeeAmount(\n params.dataStore,\n params.eventEmitter,\n market.marketToken,\n market.shortToken,\n cache.shortTokenFees.feeReceiverAmount,\n Keys.WITHDRAWAL_FEE_TYPE\n );\n\n FeeUtils.incrementClaimableUiFeeAmount(\n params.dataStore,\n params.eventEmitter,\n withdrawal.uiFeeReceiver(),\n market.marketToken,\n market.shortToken,\n cache.shortTokenFees.uiFeeAmount,\n Keys.UI_WITHDRAWAL_FEE_TYPE\n );\n\n // the pool will be reduced by the outputAmount minus the fees for the pool\n cache.longTokenPoolAmountDelta = cache.longTokenOutputAmount - cache.longTokenFees.feeAmountForPool;\n cache.longTokenOutputAmount = cache.longTokenFees.amountAfterFees;\n\n cache.shortTokenPoolAmountDelta = cache.shortTokenOutputAmount - cache.shortTokenFees.feeAmountForPool;\n cache.shortTokenOutputAmount = cache.shortTokenFees.amountAfterFees;\n\n // it is rare but possible for withdrawals to be blocked because pending borrowing fees\n // have not yet been deducted from position collateral and credited to the poolAmount value\n MarketUtils.applyDeltaToPoolAmount(\n params.dataStore,\n params.eventEmitter,\n market,\n market.longToken,\n -cache.longTokenPoolAmountDelta.toInt256()\n );\n\n MarketUtils.applyDeltaToPoolAmount(\n params.dataStore,\n params.eventEmitter,\n market,\n market.shortToken,\n -cache.shortTokenPoolAmountDelta.toInt256()\n );\n\n validateMaxLendableFactor(\n params.dataStore,\n market,\n prices\n );\n\n MarketUtils.validateReserve(params.dataStore, market, prices, true);\n\n MarketUtils.validateReserve(params.dataStore, market, prices, false);\n\n MarketUtils.validateMaxPnl(\n params.dataStore,\n market,\n prices,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS\n );\n\n MarketToken(payable(market.marketToken)).burn(address(params.withdrawalVault), withdrawal.marketTokenAmount());\n\n params.withdrawalVault.syncTokenBalance(market.marketToken);\n\n IExecuteWithdrawalUtils.ExecuteWithdrawalResult memory result;\n (result.outputToken, result.outputAmount) = _swap(\n params,\n market,\n market.longToken,\n cache.longTokenOutputAmount,\n withdrawal.longTokenSwapPath(),\n withdrawal.minLongTokenAmount(),\n withdrawal.srcChainId() == 0 ? withdrawal.receiver() : address(params.multichainVault),\n withdrawal.uiFeeReceiver(),\n withdrawal.srcChainId() == 0 ? withdrawal.shouldUnwrapNativeToken() : false\n );\n\n (result.secondaryOutputToken, result.secondaryOutputAmount) = _swap(\n params,\n market,\n market.shortToken,\n cache.shortTokenOutputAmount,\n withdrawal.shortTokenSwapPath(),\n withdrawal.minShortTokenAmount(),\n withdrawal.srcChainId() == 0 ? withdrawal.receiver() : address(params.multichainVault),\n withdrawal.uiFeeReceiver(),\n withdrawal.srcChainId() == 0 ? withdrawal.shouldUnwrapNativeToken() : false\n );\n\n // for multichain action, receiver is the multichainVault; increase user's multichain balances\n if (withdrawal.srcChainId() != 0) {\n MultichainUtils.recordTransferIn(params.dataStore, params.eventEmitter, params.multichainVault, result.outputToken, withdrawal.receiver(), 0); // srcChainId is the current block.chainId\n MultichainUtils.recordTransferIn(params.dataStore, params.eventEmitter, params.multichainVault, result.secondaryOutputToken, withdrawal.receiver(), 0); // srcChainId is the current block.chainId\n }\n\n SwapPricingUtils.emitSwapFeesCollected(\n params.eventEmitter,\n params.key,\n market.marketToken,\n market.longToken,\n prices.longTokenPrice.min,\n Keys.WITHDRAWAL_FEE_TYPE,\n cache.longTokenFees\n );\n\n SwapPricingUtils.emitSwapFeesCollected(\n params.eventEmitter,\n params.key,\n market.marketToken,\n market.shortToken,\n prices.shortTokenPrice.min,\n Keys.WITHDRAWAL_FEE_TYPE,\n cache.shortTokenFees\n );\n\n // if the native token was transferred to the receiver in a swap\n // it may be possible to invoke external contracts before the validations\n // are called\n MarketUtils.validateMarketTokenBalance(params.dataStore, market);\n\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n market,\n prices.indexTokenPrice,\n prices.longTokenPrice,\n prices.shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n false\n );\n\n uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));\n\n MarketEventUtils.emitMarketPoolValueUpdated(\n params.eventEmitter,\n keccak256(abi.encode(\"WITHDRAWAL\")),\n params.key,\n market.marketToken,\n poolValueInfo,\n marketTokensSupply\n );\n\n return result;\n }\n\n function _swap(\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params,\n Market.Props memory market,\n address tokenIn,\n uint256 amountIn,\n address[] memory swapPath,\n uint256 minOutputAmount,\n address receiver,\n address uiFeeReceiver,\n bool shouldUnwrapNativeToken\n ) internal returns (address, uint256) {\n SwapCache memory cache;\n\n cache.swapPathMarkets = MarketUtils.getSwapPathMarkets(params.dataStore, swapPath);\n\n cache.swapParams = ISwapUtils.SwapParams({\n dataStore: params.dataStore,\n eventEmitter: params.eventEmitter,\n oracle: params.oracle,\n bank: Bank(payable(market.marketToken)),\n key: params.key,\n tokenIn: tokenIn,\n amountIn: amountIn,\n swapPathMarkets: cache.swapPathMarkets,\n minOutputAmount: minOutputAmount,\n receiver: receiver,\n uiFeeReceiver: uiFeeReceiver,\n shouldUnwrapNativeToken: shouldUnwrapNativeToken,\n swapPricingType: params.swapPricingType\n });\n\n (cache.outputToken, cache.outputAmount) = params.swapHandler.swap(cache.swapParams);\n\n // validate that internal state changes are correct before calling\n // external callbacks\n MarketUtils.validateMarketTokenBalance(params.dataStore, cache.swapPathMarkets);\n\n return (cache.outputToken, cache.outputAmount);\n }\n\n function _getOutputAmounts(\n IExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices,\n uint256 marketTokenAmount\n ) internal returns (uint256, uint256) {\n // the max pnl factor for withdrawals should be the lower of the max pnl factor values\n // which means that pnl would be capped to a smaller amount and the pool\n // value would be higher even if there is a large pnl\n // this should be okay since MarketUtils.validateMaxPnl is called after the withdrawal\n // which ensures that the max pnl factor for withdrawals was not exceeded\n MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(\n params.dataStore,\n market,\n params.oracle.getPrimaryPrice(market.indexToken),\n prices.longTokenPrice,\n prices.shortTokenPrice,\n Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,\n false\n );\n\n if (poolValueInfo.poolValue <= 0) {\n revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);\n }\n\n uint256 poolValue = poolValueInfo.poolValue.toUint256();\n uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));\n uint256 withdrawalUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, poolValue, marketTokensSupply);\n\n MarketEventUtils.emitMarketPoolValueInfo(\n params.eventEmitter,\n params.key,\n market.marketToken,\n poolValueInfo,\n marketTokensSupply\n );\n\n return MarketUtils.getProportionalAmounts(\n params.dataStore,\n market,\n prices,\n withdrawalUsd\n );\n }\n\n // note that if the maxLendableImpactFactorForWithdrawals is set too large\n // it can cause withdrawals to not be executed\n function validateMaxLendableFactor(\n DataStore dataStore,\n Market.Props memory market,\n MarketUtils.MarketPrices memory prices\n ) internal view {\n uint256 longTokenUsd = MarketUtils.getPoolAmount(dataStore, market, market.longToken) * prices.longTokenPrice.min;\n uint256 shortTokenUsd = MarketUtils.getPoolAmount(dataStore, market, market.shortToken) * prices.shortTokenPrice.min;\n uint256 poolUsd = longTokenUsd + shortTokenUsd;\n\n uint256 maxLendableFactor = dataStore.getUint(Keys.maxLendableImpactFactorForWithdrawalsKey(market.marketToken));\n uint256 maxLendableUsd = Precision.applyFactor(poolUsd, maxLendableFactor);\n\n uint256 lentAmount = dataStore.getUint(Keys.lentPositionImpactPoolAmountKey(market.marketToken));\n uint256 lentUsd = lentAmount * prices.indexTokenPrice.max;\n\n if (lentUsd > maxLendableUsd) {\n revert Errors.MaxLendableFactorForWithdrawalsExceeded(poolUsd, maxLendableUsd, lentUsd);\n }\n }\n}\n" + }, + "contracts/withdrawal/IExecuteWithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\nimport \"../event/EventEmitter.sol\";\nimport \"../withdrawal/WithdrawalVault.sol\";\nimport \"../multichain/MultichainVault.sol\";\nimport \"../oracle/IOracle.sol\";\nimport \"../pricing/ISwapPricingUtils.sol\";\nimport \"../swap/ISwapHandler.sol\";\n\nimport \"../multichain/IMultichainTransferRouter.sol\";\n\ninterface IExecuteWithdrawalUtils {\n struct ExecuteWithdrawalParams {\n DataStore dataStore;\n EventEmitter eventEmitter;\n MultichainVault multichainVault;\n IMultichainTransferRouter multichainTransferRouter;\n WithdrawalVault withdrawalVault;\n IOracle oracle;\n ISwapHandler swapHandler;\n bytes32 key;\n address keeper;\n uint256 startingGas;\n ISwapPricingUtils.SwapPricingType swapPricingType;\n }\n\n struct ExecuteWithdrawalResult {\n address outputToken;\n uint256 outputAmount;\n address secondaryOutputToken;\n uint256 secondaryOutputAmount;\n }\n}\n" + }, + "contracts/withdrawal/IWithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\ninterface IWithdrawalUtils {\n /**\n * @param receiver The address that will receive the withdrawal tokens.\n * @param callbackContract The contract that will be called back.\n * @param market The market on which the withdrawal will be executed.\n * @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn.\n * @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn.\n * @param shouldUnwrapNativeToken Whether the native token should be unwrapped when executing the withdrawal.\n * @param executionFee The execution fee for the withdrawal.\n * @param callbackGasLimit The gas limit for calling the callback contract.\n * @param dataList a list of bytes32 values that can be used for additional data.\n */\n struct CreateWithdrawalParams {\n CreateWithdrawalParamsAddresses addresses;\n uint256 minLongTokenAmount;\n uint256 minShortTokenAmount;\n bool shouldUnwrapNativeToken;\n uint256 executionFee;\n uint256 callbackGasLimit;\n bytes32[] dataList;\n }\n\n struct CreateWithdrawalParamsAddresses {\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n}\n" + }, + "contracts/withdrawal/Withdrawal.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\n/**\n * @title Withdrawal\n * @dev Struct for withdrawals\n */\nlibrary Withdrawal {\n enum WithdrawalType {\n Normal,\n Shift,\n Glv\n }\n\n // @dev there is a limit on the number of fields a struct can have when being passed\n // or returned as a memory variable which can cause \"Stack too deep\" errors\n // use sub-structs to avoid this issue\n // @param addresses address values\n // @param numbers number values\n // @param flags boolean values\n // @param _dataList a list of bytes32 values that can be used for additional data\n struct Props {\n Addresses addresses;\n Numbers numbers;\n Flags flags;\n bytes32[] _dataList;\n }\n\n // @param account The account to withdraw for.\n // @param receiver The address that will receive the withdrawn tokens.\n // @param callbackContract The contract that will be called back.\n // @param uiFeeReceiver The ui fee receiver.\n // @param market The market on which the withdrawal will be executed.\n // @param longTokenSwapPath The path for swapping long tokens.\n // @param shortTokenSwapPath The path for swapping short tokens.\n struct Addresses {\n address account;\n address receiver;\n address callbackContract;\n address uiFeeReceiver;\n address market;\n address[] longTokenSwapPath;\n address[] shortTokenSwapPath;\n }\n\n // @param marketTokenAmount The amount of market tokens that will be withdrawn.\n // @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn.\n // @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn.\n // @param executionFee The execution fee for the withdrawal.\n // @param callbackGasLimit The gas limit for calling the callback contract.\n // @param srcChainId The source chain id.\n struct Numbers {\n uint256 marketTokenAmount;\n uint256 minLongTokenAmount;\n uint256 minShortTokenAmount;\n uint256 updatedAtTime;\n uint256 executionFee;\n uint256 callbackGasLimit;\n uint256 srcChainId;\n }\n\n // @param shouldUnwrapNativeToken whether to unwrap the native token when\n struct Flags {\n bool shouldUnwrapNativeToken;\n }\n\n function account(Props memory props) internal pure returns (address) {\n return props.addresses.account;\n }\n\n function setAccount(Props memory props, address value) internal pure {\n props.addresses.account = value;\n }\n\n function receiver(Props memory props) internal pure returns (address) {\n return props.addresses.receiver;\n }\n\n function setReceiver(Props memory props, address value) internal pure {\n props.addresses.receiver = value;\n }\n\n function callbackContract(Props memory props) internal pure returns (address) {\n return props.addresses.callbackContract;\n }\n\n function setCallbackContract(Props memory props, address value) internal pure {\n props.addresses.callbackContract = value;\n }\n\n function uiFeeReceiver(Props memory props) internal pure returns (address) {\n return props.addresses.uiFeeReceiver;\n }\n\n function setUiFeeReceiver(Props memory props, address value) internal pure {\n props.addresses.uiFeeReceiver = value;\n }\n\n function market(Props memory props) internal pure returns (address) {\n return props.addresses.market;\n }\n\n function setMarket(Props memory props, address value) internal pure {\n props.addresses.market = value;\n }\n\n function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.longTokenSwapPath;\n }\n\n function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.longTokenSwapPath = value;\n }\n\n function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {\n return props.addresses.shortTokenSwapPath;\n }\n\n function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {\n props.addresses.shortTokenSwapPath = value;\n }\n\n function marketTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.marketTokenAmount;\n }\n\n function setMarketTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.marketTokenAmount = value;\n }\n\n function minLongTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.minLongTokenAmount;\n }\n\n function setMinLongTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.minLongTokenAmount = value;\n }\n\n function minShortTokenAmount(Props memory props) internal pure returns (uint256) {\n return props.numbers.minShortTokenAmount;\n }\n\n function setMinShortTokenAmount(Props memory props, uint256 value) internal pure {\n props.numbers.minShortTokenAmount = value;\n }\n\n function updatedAtTime(Props memory props) internal pure returns (uint256) {\n return props.numbers.updatedAtTime;\n }\n\n function setUpdatedAtTime(Props memory props, uint256 value) internal pure {\n props.numbers.updatedAtTime = value;\n }\n\n function executionFee(Props memory props) internal pure returns (uint256) {\n return props.numbers.executionFee;\n }\n\n function setExecutionFee(Props memory props, uint256 value) internal pure {\n props.numbers.executionFee = value;\n }\n\n function callbackGasLimit(Props memory props) internal pure returns (uint256) {\n return props.numbers.callbackGasLimit;\n }\n\n function setCallbackGasLimit(Props memory props, uint256 value) internal pure {\n props.numbers.callbackGasLimit = value;\n }\n\n function srcChainId(Props memory props) internal pure returns (uint256) {\n return props.numbers.srcChainId;\n }\n\n function setSrcChainId(Props memory props, uint256 value) internal pure {\n props.numbers.srcChainId = value;\n }\n\n function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {\n return props.flags.shouldUnwrapNativeToken;\n }\n\n function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {\n props.flags.shouldUnwrapNativeToken = value;\n }\n\n function dataList(Props memory props) internal pure returns (bytes32[] memory) {\n return props._dataList;\n }\n\n function setDataList(Props memory props, bytes32[] memory value) internal pure {\n props._dataList = value;\n }\n}\n" + }, + "contracts/withdrawal/WithdrawalEventUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../event/EventEmitter.sol\";\nimport \"../event/EventUtils.sol\";\nimport \"../utils/Cast.sol\";\n\nimport \"./Withdrawal.sol\";\nimport \"../pricing/ISwapPricingUtils.sol\";\n\nlibrary WithdrawalEventUtils {\n using Withdrawal for Withdrawal.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n function emitWithdrawalCreated(\n EventEmitter eventEmitter,\n bytes32 key,\n Withdrawal.Props memory withdrawal,\n Withdrawal.WithdrawalType withdrawalType\n ) external {\n EventUtils.EventLogData memory eventData = createEventData(withdrawal, withdrawalType);\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventEmitter.emitEventLog2(\n \"WithdrawalCreated\",\n key,\n Cast.toBytes32(withdrawal.account()),\n eventData\n );\n }\n\n function emitWithdrawalExecuted(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n ISwapPricingUtils.SwapPricingType swapPricingType\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.uintItems.initItems(1);\n eventData.uintItems.setItem(0, \"swapPricingType\", uint256(swapPricingType));\n\n eventEmitter.emitEventLog2(\n \"WithdrawalExecuted\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function emitWithdrawalCancelled(\n EventEmitter eventEmitter,\n bytes32 key,\n address account,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n EventUtils.EventLogData memory eventData;\n\n eventData.bytes32Items.initItems(1);\n eventData.bytes32Items.setItem(0, \"key\", key);\n\n eventData.addressItems.initItems(1);\n eventData.addressItems.setItem(0, \"account\", account);\n\n eventData.stringItems.initItems(1);\n eventData.stringItems.setItem(0, \"reason\", reason);\n\n eventData.bytesItems.initItems(1);\n eventData.bytesItems.setItem(0, \"reasonBytes\", reasonBytes);\n\n eventEmitter.emitEventLog2(\n \"WithdrawalCancelled\",\n key,\n Cast.toBytes32(account),\n eventData\n );\n }\n\n function createEventData(Withdrawal.Props memory withdrawal, Withdrawal.WithdrawalType withdrawalType)\n public pure returns(EventUtils.EventLogData memory) {\n EventUtils.EventLogData memory eventData;\n\n eventData.addressItems.initItems(5);\n eventData.addressItems.setItem(0, \"account\", withdrawal.account());\n eventData.addressItems.setItem(1, \"receiver\", withdrawal.receiver());\n eventData.addressItems.setItem(2, \"callbackContract\", withdrawal.callbackContract());\n eventData.addressItems.setItem(3, \"market\", withdrawal.market());\n eventData.addressItems.setItem(4, \"uiFeeReceiver\", withdrawal.uiFeeReceiver());\n\n eventData.addressItems.initArrayItems(2);\n eventData.addressItems.setItem(0, \"longTokenSwapPath\", withdrawal.longTokenSwapPath());\n eventData.addressItems.setItem(1, \"shortTokenSwapPath\", withdrawal.shortTokenSwapPath());\n\n eventData.uintItems.initItems(8);\n eventData.uintItems.setItem(0, \"marketTokenAmount\", withdrawal.marketTokenAmount());\n eventData.uintItems.setItem(1, \"minLongTokenAmount\", withdrawal.minLongTokenAmount());\n eventData.uintItems.setItem(2, \"minShortTokenAmount\", withdrawal.minShortTokenAmount());\n eventData.uintItems.setItem(3, \"updatedAtTime\", withdrawal.updatedAtTime());\n eventData.uintItems.setItem(4, \"executionFee\", withdrawal.executionFee());\n eventData.uintItems.setItem(5, \"callbackGasLimit\", withdrawal.callbackGasLimit());\n eventData.uintItems.setItem(6, \"withdrawalType\", uint256(withdrawalType));\n eventData.uintItems.setItem(7, \"srcChainId\", withdrawal.srcChainId());\n\n eventData.boolItems.initItems(1);\n eventData.boolItems.setItem(0, \"shouldUnwrapNativeToken\", withdrawal.shouldUnwrapNativeToken());\n\n eventData.bytes32Items.initArrayItems(1);\n eventData.bytes32Items.setItem(0, \"dataList\", withdrawal.dataList());\n return eventData;\n }\n}\n" + }, + "contracts/withdrawal/WithdrawalStoreUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/Keys.sol\";\nimport \"../data/DataStore.sol\";\n\nimport \"./Withdrawal.sol\";\n\n/**\n * @title WithdrawalStoreUtils\n * @dev Library for withdrawal storage functions\n */\nlibrary WithdrawalStoreUtils {\n using Withdrawal for Withdrawal.Props;\n\n bytes32 public constant ACCOUNT = keccak256(abi.encode(\"ACCOUNT\"));\n bytes32 public constant RECEIVER = keccak256(abi.encode(\"RECEIVER\"));\n bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode(\"CALLBACK_CONTRACT\"));\n bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode(\"UI_FEE_RECEIVER\"));\n bytes32 public constant MARKET = keccak256(abi.encode(\"MARKET\"));\n bytes32 public constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode(\"LONG_TOKEN_SWAP_PATH\"));\n bytes32 public constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode(\"SHORT_TOKEN_SWAP_PATH\"));\n\n bytes32 public constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode(\"MARKET_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_LONG_TOKEN_AMOUNT = keccak256(abi.encode(\"MIN_LONG_TOKEN_AMOUNT\"));\n bytes32 public constant MIN_SHORT_TOKEN_AMOUNT = keccak256(abi.encode(\"MIN_SHORT_TOKEN_AMOUNT\"));\n bytes32 public constant UPDATED_AT_TIME = keccak256(abi.encode(\"UPDATED_AT_TIME\"));\n bytes32 public constant EXECUTION_FEE = keccak256(abi.encode(\"EXECUTION_FEE\"));\n bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode(\"CALLBACK_GAS_LIMIT\"));\n bytes32 public constant SRC_CHAIN_ID = keccak256(abi.encode(\"SRC_CHAIN_ID\"));\n\n bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode(\"SHOULD_UNWRAP_NATIVE_TOKEN\"));\n\n bytes32 public constant DATA_LIST = keccak256(abi.encode(\"DATA_LIST\"));\n\n function get(DataStore dataStore, bytes32 key) external view returns (Withdrawal.Props memory) {\n Withdrawal.Props memory withdrawal;\n if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) {\n return withdrawal;\n }\n\n withdrawal.setAccount(dataStore.getAddress(\n keccak256(abi.encode(key, ACCOUNT))\n ));\n\n withdrawal.setReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, RECEIVER))\n ));\n\n withdrawal.setCallbackContract(dataStore.getAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n ));\n\n withdrawal.setUiFeeReceiver(dataStore.getAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n ));\n\n withdrawal.setMarket(dataStore.getAddress(\n keccak256(abi.encode(key, MARKET))\n ));\n\n withdrawal.setLongTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n ));\n\n withdrawal.setShortTokenSwapPath(dataStore.getAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n ));\n\n withdrawal.setMarketTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n ));\n\n withdrawal.setMinLongTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))\n ));\n\n withdrawal.setMinShortTokenAmount(dataStore.getUint(\n keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))\n ));\n\n withdrawal.setUpdatedAtTime(dataStore.getUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n ));\n\n withdrawal.setExecutionFee(dataStore.getUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n ));\n\n withdrawal.setCallbackGasLimit(dataStore.getUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n ));\n\n withdrawal.setSrcChainId(dataStore.getUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n ));\n\n withdrawal.setShouldUnwrapNativeToken(dataStore.getBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n ));\n\n withdrawal.setDataList(dataStore.getBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n ));\n\n return withdrawal;\n }\n\n function set(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) external {\n dataStore.addBytes32(\n Keys.WITHDRAWAL_LIST,\n key\n );\n\n dataStore.addBytes32(\n Keys.accountWithdrawalListKey(withdrawal.account()),\n key\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, ACCOUNT)),\n withdrawal.account()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, RECEIVER)),\n withdrawal.receiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT)),\n withdrawal.callbackContract()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER)),\n withdrawal.uiFeeReceiver()\n );\n\n dataStore.setAddress(\n keccak256(abi.encode(key, MARKET)),\n withdrawal.market()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),\n withdrawal.longTokenSwapPath()\n );\n\n dataStore.setAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),\n withdrawal.shortTokenSwapPath()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),\n withdrawal.marketTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)),\n withdrawal.minLongTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)),\n withdrawal.minShortTokenAmount()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME)),\n withdrawal.updatedAtTime()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, EXECUTION_FEE)),\n withdrawal.executionFee()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),\n withdrawal.callbackGasLimit()\n );\n\n dataStore.setUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID)),\n withdrawal.srcChainId()\n );\n\n dataStore.setBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),\n withdrawal.shouldUnwrapNativeToken()\n );\n\n dataStore.setBytes32Array(\n keccak256(abi.encode(key, DATA_LIST)),\n withdrawal.dataList()\n );\n }\n\n function remove(DataStore dataStore, bytes32 key, address account) external {\n if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) {\n revert Errors.WithdrawalNotFound(key);\n }\n\n dataStore.removeBytes32(\n Keys.WITHDRAWAL_LIST,\n key\n );\n\n dataStore.removeBytes32(\n Keys.accountWithdrawalListKey(account),\n key\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, ACCOUNT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, CALLBACK_CONTRACT))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, UI_FEE_RECEIVER))\n );\n\n dataStore.removeAddress(\n keccak256(abi.encode(key, MARKET))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeAddressArray(\n keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, UPDATED_AT_TIME))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, EXECUTION_FEE))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, SRC_CHAIN_ID))\n );\n\n dataStore.removeUint(\n keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))\n );\n\n dataStore.removeBool(\n keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))\n );\n\n dataStore.removeBytes32Array(\n keccak256(abi.encode(key, DATA_LIST))\n );\n }\n\n function getWithdrawalCount(DataStore dataStore) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.WITHDRAWAL_LIST);\n }\n\n function getWithdrawalKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.WITHDRAWAL_LIST, start, end);\n }\n\n function getAccountWithdrawalCount(DataStore dataStore, address account) internal view returns (uint256) {\n return dataStore.getBytes32Count(Keys.accountWithdrawalListKey(account));\n }\n\n function getAccountWithdrawalKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n return dataStore.getBytes32ValuesAt(Keys.accountWithdrawalListKey(account), start, end);\n }\n}\n" + }, + "contracts/withdrawal/WithdrawalUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../data/DataStore.sol\";\n\nimport \"./WithdrawalVault.sol\";\nimport \"./WithdrawalStoreUtils.sol\";\nimport \"./WithdrawalEventUtils.sol\";\nimport \"./IWithdrawalUtils.sol\";\n\nimport \"../nonce/NonceUtils.sol\";\n\nimport \"../gas/GasUtils.sol\";\nimport \"../callback/CallbackUtils.sol\";\n\nimport \"../price/Price.sol\";\nimport \"../market/MarketUtils.sol\";\nimport \"../utils/Array.sol\";\nimport \"../utils/AccountUtils.sol\";\n\nimport \"../multichain/MultichainVault.sol\";\n\n/**\n * @title WithdrawalUtils\n * @dev Library for withdrawal functions\n */\nlibrary WithdrawalUtils {\n using SafeCast for uint256;\n using SafeCast for int256;\n using Array for uint256[];\n using Price for Price.Props;\n using Withdrawal for Withdrawal.Props;\n\n using EventUtils for EventUtils.AddressItems;\n using EventUtils for EventUtils.UintItems;\n using EventUtils for EventUtils.IntItems;\n using EventUtils for EventUtils.BoolItems;\n using EventUtils for EventUtils.Bytes32Items;\n using EventUtils for EventUtils.BytesItems;\n using EventUtils for EventUtils.StringItems;\n\n /**\n * @dev Creates a withdrawal in the withdrawal store.\n *\n * @param dataStore The data store where withdrawal data is stored.\n * @param eventEmitter The event emitter that is used to emit events.\n * @param withdrawalVault WithdrawalVault.\n * @param account The account that initiated the withdrawal.\n * @param srcChainId The source chain id for the withdrawal.\n * @param params The parameters for creating the withdrawal.\n * @param isAtomicWithdrawal Whether the withdrawal is atomic.\n * @return The unique identifier of the created withdrawal.\n */\n function createWithdrawal(\n DataStore dataStore,\n EventEmitter eventEmitter,\n WithdrawalVault withdrawalVault,\n address account,\n uint256 srcChainId,\n IWithdrawalUtils.CreateWithdrawalParams memory params,\n bool isAtomicWithdrawal\n ) external returns (bytes32) {\n AccountUtils.validateAccount(account);\n\n address wnt = TokenUtils.wnt(dataStore);\n uint256 wntAmount = withdrawalVault.recordTransferIn(wnt);\n\n if (wntAmount < params.executionFee) {\n revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);\n }\n\n AccountUtils.validateReceiver(params.addresses.receiver);\n\n uint256 marketTokenAmount = withdrawalVault.recordTransferIn(params.addresses.market);\n\n if (marketTokenAmount == 0) {\n revert Errors.EmptyWithdrawalAmount();\n }\n params.executionFee = wntAmount;\n\n MarketUtils.validateEnabledMarket(dataStore, params.addresses.market);\n MarketUtils.validateSwapPath(dataStore, params.addresses.longTokenSwapPath);\n MarketUtils.validateSwapPath(dataStore, params.addresses.shortTokenSwapPath);\n\n Withdrawal.Props memory withdrawal = Withdrawal.Props(\n Withdrawal.Addresses(\n account,\n params.addresses.receiver,\n params.addresses.callbackContract,\n params.addresses.uiFeeReceiver,\n params.addresses.market,\n params.addresses.longTokenSwapPath,\n params.addresses.shortTokenSwapPath\n ),\n Withdrawal.Numbers(\n marketTokenAmount,\n params.minLongTokenAmount,\n params.minShortTokenAmount,\n Chain.currentTimestamp(), // updatedAtTime\n params.executionFee,\n params.callbackGasLimit,\n srcChainId\n ),\n Withdrawal.Flags(\n params.shouldUnwrapNativeToken\n ),\n params.dataList\n );\n\n CallbackUtils.validateCallbackGasLimit(dataStore, withdrawal.callbackGasLimit());\n\n if (!isAtomicWithdrawal) {\n uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal);\n uint256 oraclePriceCount = GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length);\n GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount);\n }\n\n bytes32 key = NonceUtils.getNextKey(dataStore);\n\n WithdrawalStoreUtils.set(dataStore, key, withdrawal);\n\n WithdrawalEventUtils.emitWithdrawalCreated(eventEmitter, key, withdrawal, Withdrawal.WithdrawalType.Normal);\n\n return key;\n }\n\n /**\n * @dev Cancels a withdrawal.\n * @param dataStore The data store.\n * @param eventEmitter The event emitter.\n * @param withdrawalVault The withdrawal vault.\n * @param key The withdrawal key.\n * @param keeper The keeper sending the transaction.\n * @param startingGas The starting gas for the transaction.\n */\n function cancelWithdrawal(\n DataStore dataStore,\n EventEmitter eventEmitter,\n MultichainVault multichainVault,\n WithdrawalVault withdrawalVault,\n bytes32 key,\n address keeper,\n uint256 startingGas,\n string memory reason,\n bytes memory reasonBytes\n ) external {\n // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this\n startingGas -= gasleft() / 63;\n\n Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);\n\n if (withdrawal.account() == address(0)) {\n revert Errors.EmptyWithdrawal();\n }\n\n if (withdrawal.marketTokenAmount() == 0) {\n revert Errors.EmptyWithdrawalAmount();\n }\n\n WithdrawalStoreUtils.remove(dataStore, key, withdrawal.account());\n\n if (withdrawal.srcChainId() == 0) {\n withdrawalVault.transferOut(\n withdrawal.market(),\n withdrawal.account(),\n withdrawal.marketTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n } else {\n withdrawalVault.transferOut(\n withdrawal.market(),\n address(multichainVault),\n withdrawal.marketTokenAmount(),\n false // shouldUnwrapNativeToken\n );\n MultichainUtils.recordTransferIn(\n dataStore,\n eventEmitter,\n multichainVault,\n withdrawal.market(),\n withdrawal.account(),\n 0 // srcChainId is the current block.chainId\n );\n }\n\n\n WithdrawalEventUtils.emitWithdrawalCancelled(\n eventEmitter,\n key,\n withdrawal.account(),\n reason,\n reasonBytes\n );\n\n EventUtils.EventLogData memory eventData;\n CallbackUtils.afterWithdrawalCancellation(key, withdrawal, eventData);\n\n GasUtils.payExecutionFee(\n GasUtils.PayExecutionFeeContracts(\n dataStore,\n eventEmitter,\n multichainVault,\n withdrawalVault\n ),\n key,\n withdrawal.callbackContract(),\n withdrawal.executionFee(),\n startingGas,\n GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length),\n keeper,\n withdrawal.receiver(),\n withdrawal.srcChainId()\n );\n }\n}\n" + }, + "contracts/withdrawal/WithdrawalVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"../bank/StrictBank.sol\";\n\n// @title WithdrawalVault\n// @dev Vault for withdrawals\ncontract WithdrawalVault is StrictBank {\n constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}\n}\n" + }, + "prb-math/contracts/PRBMath.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\n/// @notice Emitted when the result overflows uint256.\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\n\n/// @notice Emitted when the result overflows uint256.\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\n\n/// @notice Emitted when one of the inputs is type(int256).min.\nerror PRBMath__MulDivSignedInputTooSmall();\n\n/// @notice Emitted when the intermediary absolute result overflows int256.\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is MIN_SD59x18.\nerror PRBMathSD59x18__AbsInputTooSmall();\n\n/// @notice Emitted when ceiling a number overflows SD59x18.\nerror PRBMathSD59x18__CeilOverflow(int256 x);\n\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\nerror PRBMathSD59x18__DivInputTooSmall();\n\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is greater than 133.084258667509499441.\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\n\n/// @notice Emitted when the input is greater than 192.\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\n\n/// @notice Emitted when flooring a number underflows SD59x18.\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\n\n/// @notice Emitted when the product of the inputs is negative.\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\n\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\n\n/// @notice Emitted when the input is less than or equal to zero.\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\n\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\nerror PRBMathSD59x18__MulInputTooSmall();\n\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\n\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is negative.\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\n\n/// @notice Emitted when the calculating the square root overflows SD59x18.\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\n\n/// @notice Emitted when addition overflows UD60x18.\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\n\n/// @notice Emitted when ceiling a number overflows UD60x18.\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\n\n/// @notice Emitted when the input is greater than 133.084258667509499441.\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\n\n/// @notice Emitted when the input is greater than 192.\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\n\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\n\n/// @notice Emitted when the input is less than 1.\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\n\n/// @notice Emitted when the calculating the square root overflows UD60x18.\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\n\n/// @notice Emitted when subtraction underflows UD60x18.\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\n\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\nlibrary PRBMath {\n /// STRUCTS ///\n\n struct SD59x18 {\n int256 value;\n }\n\n struct UD60x18 {\n uint256 value;\n }\n\n /// STORAGE ///\n\n /// @dev How many trailing decimals can be represented.\n uint256 internal constant SCALE = 1e18;\n\n /// @dev Largest power of two divisor of SCALE.\n uint256 internal constant SCALE_LPOTD = 262144;\n\n /// @dev SCALE inverted mod 2^256.\n uint256 internal constant SCALE_INVERSE =\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\n\n /// FUNCTIONS ///\n\n /// @notice Calculates the binary exponent of x using the binary fraction method.\n /// @dev Has to use 192.64-bit fixed-point numbers.\n /// See https://ethereum.stackexchange.com/a/96594/24693.\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n function exp2(uint256 x) internal pure returns (uint256 result) {\n unchecked {\n // Start from 0.5 in the 192.64-bit fixed-point format.\n result = 0x800000000000000000000000000000000000000000000000;\n\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\n // because the initial result is 2^191 and all magic factors are less than 2^65.\n if (x & 0x8000000000000000 > 0) {\n result = (result * 0x16A09E667F3BCC909) >> 64;\n }\n if (x & 0x4000000000000000 > 0) {\n result = (result * 0x1306FE0A31B7152DF) >> 64;\n }\n if (x & 0x2000000000000000 > 0) {\n result = (result * 0x1172B83C7D517ADCE) >> 64;\n }\n if (x & 0x1000000000000000 > 0) {\n result = (result * 0x10B5586CF9890F62A) >> 64;\n }\n if (x & 0x800000000000000 > 0) {\n result = (result * 0x1059B0D31585743AE) >> 64;\n }\n if (x & 0x400000000000000 > 0) {\n result = (result * 0x102C9A3E778060EE7) >> 64;\n }\n if (x & 0x200000000000000 > 0) {\n result = (result * 0x10163DA9FB33356D8) >> 64;\n }\n if (x & 0x100000000000000 > 0) {\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\n }\n if (x & 0x80000000000000 > 0) {\n result = (result * 0x10058C86DA1C09EA2) >> 64;\n }\n if (x & 0x40000000000000 > 0) {\n result = (result * 0x1002C605E2E8CEC50) >> 64;\n }\n if (x & 0x20000000000000 > 0) {\n result = (result * 0x100162F3904051FA1) >> 64;\n }\n if (x & 0x10000000000000 > 0) {\n result = (result * 0x1000B175EFFDC76BA) >> 64;\n }\n if (x & 0x8000000000000 > 0) {\n result = (result * 0x100058BA01FB9F96D) >> 64;\n }\n if (x & 0x4000000000000 > 0) {\n result = (result * 0x10002C5CC37DA9492) >> 64;\n }\n if (x & 0x2000000000000 > 0) {\n result = (result * 0x1000162E525EE0547) >> 64;\n }\n if (x & 0x1000000000000 > 0) {\n result = (result * 0x10000B17255775C04) >> 64;\n }\n if (x & 0x800000000000 > 0) {\n result = (result * 0x1000058B91B5BC9AE) >> 64;\n }\n if (x & 0x400000000000 > 0) {\n result = (result * 0x100002C5C89D5EC6D) >> 64;\n }\n if (x & 0x200000000000 > 0) {\n result = (result * 0x10000162E43F4F831) >> 64;\n }\n if (x & 0x100000000000 > 0) {\n result = (result * 0x100000B1721BCFC9A) >> 64;\n }\n if (x & 0x80000000000 > 0) {\n result = (result * 0x10000058B90CF1E6E) >> 64;\n }\n if (x & 0x40000000000 > 0) {\n result = (result * 0x1000002C5C863B73F) >> 64;\n }\n if (x & 0x20000000000 > 0) {\n result = (result * 0x100000162E430E5A2) >> 64;\n }\n if (x & 0x10000000000 > 0) {\n result = (result * 0x1000000B172183551) >> 64;\n }\n if (x & 0x8000000000 > 0) {\n result = (result * 0x100000058B90C0B49) >> 64;\n }\n if (x & 0x4000000000 > 0) {\n result = (result * 0x10000002C5C8601CC) >> 64;\n }\n if (x & 0x2000000000 > 0) {\n result = (result * 0x1000000162E42FFF0) >> 64;\n }\n if (x & 0x1000000000 > 0) {\n result = (result * 0x10000000B17217FBB) >> 64;\n }\n if (x & 0x800000000 > 0) {\n result = (result * 0x1000000058B90BFCE) >> 64;\n }\n if (x & 0x400000000 > 0) {\n result = (result * 0x100000002C5C85FE3) >> 64;\n }\n if (x & 0x200000000 > 0) {\n result = (result * 0x10000000162E42FF1) >> 64;\n }\n if (x & 0x100000000 > 0) {\n result = (result * 0x100000000B17217F8) >> 64;\n }\n if (x & 0x80000000 > 0) {\n result = (result * 0x10000000058B90BFC) >> 64;\n }\n if (x & 0x40000000 > 0) {\n result = (result * 0x1000000002C5C85FE) >> 64;\n }\n if (x & 0x20000000 > 0) {\n result = (result * 0x100000000162E42FF) >> 64;\n }\n if (x & 0x10000000 > 0) {\n result = (result * 0x1000000000B17217F) >> 64;\n }\n if (x & 0x8000000 > 0) {\n result = (result * 0x100000000058B90C0) >> 64;\n }\n if (x & 0x4000000 > 0) {\n result = (result * 0x10000000002C5C860) >> 64;\n }\n if (x & 0x2000000 > 0) {\n result = (result * 0x1000000000162E430) >> 64;\n }\n if (x & 0x1000000 > 0) {\n result = (result * 0x10000000000B17218) >> 64;\n }\n if (x & 0x800000 > 0) {\n result = (result * 0x1000000000058B90C) >> 64;\n }\n if (x & 0x400000 > 0) {\n result = (result * 0x100000000002C5C86) >> 64;\n }\n if (x & 0x200000 > 0) {\n result = (result * 0x10000000000162E43) >> 64;\n }\n if (x & 0x100000 > 0) {\n result = (result * 0x100000000000B1721) >> 64;\n }\n if (x & 0x80000 > 0) {\n result = (result * 0x10000000000058B91) >> 64;\n }\n if (x & 0x40000 > 0) {\n result = (result * 0x1000000000002C5C8) >> 64;\n }\n if (x & 0x20000 > 0) {\n result = (result * 0x100000000000162E4) >> 64;\n }\n if (x & 0x10000 > 0) {\n result = (result * 0x1000000000000B172) >> 64;\n }\n if (x & 0x8000 > 0) {\n result = (result * 0x100000000000058B9) >> 64;\n }\n if (x & 0x4000 > 0) {\n result = (result * 0x10000000000002C5D) >> 64;\n }\n if (x & 0x2000 > 0) {\n result = (result * 0x1000000000000162E) >> 64;\n }\n if (x & 0x1000 > 0) {\n result = (result * 0x10000000000000B17) >> 64;\n }\n if (x & 0x800 > 0) {\n result = (result * 0x1000000000000058C) >> 64;\n }\n if (x & 0x400 > 0) {\n result = (result * 0x100000000000002C6) >> 64;\n }\n if (x & 0x200 > 0) {\n result = (result * 0x10000000000000163) >> 64;\n }\n if (x & 0x100 > 0) {\n result = (result * 0x100000000000000B1) >> 64;\n }\n if (x & 0x80 > 0) {\n result = (result * 0x10000000000000059) >> 64;\n }\n if (x & 0x40 > 0) {\n result = (result * 0x1000000000000002C) >> 64;\n }\n if (x & 0x20 > 0) {\n result = (result * 0x10000000000000016) >> 64;\n }\n if (x & 0x10 > 0) {\n result = (result * 0x1000000000000000B) >> 64;\n }\n if (x & 0x8 > 0) {\n result = (result * 0x10000000000000006) >> 64;\n }\n if (x & 0x4 > 0) {\n result = (result * 0x10000000000000003) >> 64;\n }\n if (x & 0x2 > 0) {\n result = (result * 0x10000000000000001) >> 64;\n }\n if (x & 0x1 > 0) {\n result = (result * 0x10000000000000001) >> 64;\n }\n\n // We're doing two things at the same time:\n //\n // 1. Multiply the result by 2^n + 1, where \"2^n\" is the integer part and the one is added to account for\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\n // rather than 192.\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\n //\n // This works because 2^(191-ip) = 2^ip / 2^191, where \"ip\" is the integer part \"2^n\".\n result *= SCALE;\n result >>= (191 - (x >> 64));\n }\n }\n\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\n /// @dev See the note on msb in the \"Find First Set\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\n /// @param x The uint256 number for which to find the index of the most significant bit.\n /// @return msb The index of the most significant bit as an uint256.\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n if (x >= 2**128) {\n x >>= 128;\n msb += 128;\n }\n if (x >= 2**64) {\n x >>= 64;\n msb += 64;\n }\n if (x >= 2**32) {\n x >>= 32;\n msb += 32;\n }\n if (x >= 2**16) {\n x >>= 16;\n msb += 16;\n }\n if (x >= 2**8) {\n x >>= 8;\n msb += 8;\n }\n if (x >= 2**4) {\n x >>= 4;\n msb += 4;\n }\n if (x >= 2**2) {\n x >>= 2;\n msb += 2;\n }\n if (x >= 2**1) {\n // No need to shift x any more.\n msb += 1;\n }\n }\n\n /// @notice Calculates floor(x*y÷denominator) with full precision.\n ///\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\n ///\n /// Requirements:\n /// - The denominator cannot be zero.\n /// - The result must fit within uint256.\n ///\n /// Caveats:\n /// - This function does not work with fixed-point numbers.\n ///\n /// @param x The multiplicand as an uint256.\n /// @param y The multiplier as an uint256.\n /// @param denominator The divisor as an uint256.\n /// @return result The result as an uint256.\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n unchecked {\n result = prod0 / denominator;\n }\n return result;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n if (prod1 >= denominator) {\n revert PRBMath__MulDivOverflow(prod1, denominator);\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n unchecked {\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 lpotdod = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by lpotdod.\n denominator := div(denominator, lpotdod)\n\n // Divide [prod1 prod0] by lpotdod.\n prod0 := div(prod0, lpotdod)\n\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * lpotdod;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /// @notice Calculates floor(x*y÷1e18) with full precision.\n ///\n /// @dev Variant of \"mulDiv\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\n /// being rounded to 1e-18. See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717.\n ///\n /// Requirements:\n /// - The result must fit within uint256.\n ///\n /// Caveats:\n /// - The body is purposely left uncommented; see the NatSpec comments in \"PRBMath.mulDiv\" to understand how this works.\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\n /// 1. x * y = type(uint256).max * SCALE\n /// 2. (x * y) % SCALE >= SCALE / 2\n ///\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\n uint256 prod0;\n uint256 prod1;\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n if (prod1 >= SCALE) {\n revert PRBMath__MulDivFixedPointOverflow(prod1);\n }\n\n uint256 remainder;\n uint256 roundUpUnit;\n assembly {\n remainder := mulmod(x, y, SCALE)\n roundUpUnit := gt(remainder, 499999999999999999)\n }\n\n if (prod1 == 0) {\n unchecked {\n result = (prod0 / SCALE) + roundUpUnit;\n return result;\n }\n }\n\n assembly {\n result := add(\n mul(\n or(\n div(sub(prod0, remainder), SCALE_LPOTD),\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\n ),\n SCALE_INVERSE\n ),\n roundUpUnit\n )\n }\n }\n\n /// @notice Calculates floor(x*y÷denominator) with full precision.\n ///\n /// @dev An extension of \"mulDiv\" for signed numbers. Works by computing the signs and the absolute values separately.\n ///\n /// Requirements:\n /// - None of the inputs can be type(int256).min.\n /// - The result must fit within int256.\n ///\n /// @param x The multiplicand as an int256.\n /// @param y The multiplier as an int256.\n /// @param denominator The divisor as an int256.\n /// @return result The result as an int256.\n function mulDivSigned(\n int256 x,\n int256 y,\n int256 denominator\n ) internal pure returns (int256 result) {\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\n revert PRBMath__MulDivSignedInputTooSmall();\n }\n\n // Get hold of the absolute values of x, y and the denominator.\n uint256 ax;\n uint256 ay;\n uint256 ad;\n unchecked {\n ax = x < 0 ? uint256(-x) : uint256(x);\n ay = y < 0 ? uint256(-y) : uint256(y);\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\n }\n\n // Compute the absolute value of (x*y)÷denominator. The result must fit within int256.\n uint256 rAbs = mulDiv(ax, ay, ad);\n if (rAbs > uint256(type(int256).max)) {\n revert PRBMath__MulDivSignedOverflow(rAbs);\n }\n\n // Get the signs of x, y and the denominator.\n uint256 sx;\n uint256 sy;\n uint256 sd;\n assembly {\n sx := sgt(x, sub(0, 1))\n sy := sgt(y, sub(0, 1))\n sd := sgt(denominator, sub(0, 1))\n }\n\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\n // If yes, the result should be negative.\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\n }\n\n /// @notice Calculates the square root of x, rounding down.\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n ///\n /// Caveats:\n /// - This function does not work with fixed-point numbers.\n ///\n /// @param x The uint256 number for which to calculate the square root.\n /// @return result The result as an uint256.\n function sqrt(uint256 x) internal pure returns (uint256 result) {\n if (x == 0) {\n return 0;\n }\n\n // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\n uint256 xAux = uint256(x);\n result = 1;\n if (xAux >= 0x100000000000000000000000000000000) {\n xAux >>= 128;\n result <<= 64;\n }\n if (xAux >= 0x10000000000000000) {\n xAux >>= 64;\n result <<= 32;\n }\n if (xAux >= 0x100000000) {\n xAux >>= 32;\n result <<= 16;\n }\n if (xAux >= 0x10000) {\n xAux >>= 16;\n result <<= 8;\n }\n if (xAux >= 0x100) {\n xAux >>= 8;\n result <<= 4;\n }\n if (xAux >= 0x10) {\n xAux >>= 4;\n result <<= 2;\n }\n if (xAux >= 0x8) {\n result <<= 1;\n }\n\n // The operations can never overflow because the result is max 2^127 when it enters this block.\n unchecked {\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1;\n result = (result + x / result) >> 1; // Seven iterations should be enough\n uint256 roundedDownResult = x / result;\n return result >= roundedDownResult ? roundedDownResult : result;\n }\n }\n}\n" + }, + "prb-math/contracts/PRBMathUD60x18.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"./PRBMath.sol\";\n\n/// @title PRBMathUD60x18\n/// @author Paul Razvan Berg\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\n/// maximum values permitted by the Solidity type uint256.\nlibrary PRBMathUD60x18 {\n /// @dev Half the SCALE number.\n uint256 internal constant HALF_SCALE = 5e17;\n\n /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\n uint256 internal constant LOG2_E = 1_442695040888963407;\n\n /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\n uint256 internal constant MAX_UD60x18 =\n 115792089237316195423570985008687907853269984665640564039457_584007913129639935;\n\n /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\n uint256 internal constant MAX_WHOLE_UD60x18 =\n 115792089237316195423570985008687907853269984665640564039457_000000000000000000;\n\n /// @dev How many trailing decimals can be represented.\n uint256 internal constant SCALE = 1e18;\n\n /// @notice Calculates the arithmetic average of x and y, rounding down.\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\n /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\n function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\n // The operations can never overflow.\n unchecked {\n // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\n // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\n result = (x >> 1) + (y >> 1) + (x & y & 1);\n }\n }\n\n /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\n ///\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n ///\n /// Requirements:\n /// - x must be less than or equal to MAX_WHOLE_UD60x18.\n ///\n /// @param x The unsigned 60.18-decimal fixed-point number to ceil.\n /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\n function ceil(uint256 x) internal pure returns (uint256 result) {\n if (x > MAX_WHOLE_UD60x18) {\n revert PRBMathUD60x18__CeilOverflow(x);\n }\n assembly {\n // Equivalent to \"x % SCALE\" but faster.\n let remainder := mod(x, SCALE)\n\n // Equivalent to \"SCALE - remainder\" but faster.\n let delta := sub(SCALE, remainder)\n\n // Equivalent to \"x + delta * (remainder > 0 ? 1 : 0)\" but faster.\n result := add(x, mul(delta, gt(remainder, 0)))\n }\n }\n\n /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\n ///\n /// @dev Uses mulDiv to enable overflow-safe multiplication and division.\n ///\n /// Requirements:\n /// - The denominator cannot be zero.\n ///\n /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\n /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\n /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\n function div(uint256 x, uint256 y) internal pure returns (uint256 result) {\n result = PRBMath.mulDiv(x, SCALE, y);\n }\n\n /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.\n /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\n function e() internal pure returns (uint256 result) {\n result = 2_718281828459045235;\n }\n\n /// @notice Calculates the natural exponent of x.\n ///\n /// @dev Based on the insight that e^x = 2^(x * log2(e)).\n ///\n /// Requirements:\n /// - All from \"log2\".\n /// - x must be less than 133.084258667509499441.\n ///\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n function exp(uint256 x) internal pure returns (uint256 result) {\n // Without this check, the value passed to \"exp2\" would be greater than 192.\n if (x >= 133_084258667509499441) {\n revert PRBMathUD60x18__ExpInputTooBig(x);\n }\n\n // Do the fixed-point multiplication inline to save gas.\n unchecked {\n uint256 doubleScaleProduct = x * LOG2_E;\n result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\n }\n }\n\n /// @notice Calculates the binary exponent of x using the binary fraction method.\n ///\n /// @dev See https://ethereum.stackexchange.com/q/79903/24693.\n ///\n /// Requirements:\n /// - x must be 192 or less.\n /// - The result must fit within MAX_UD60x18.\n ///\n /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n function exp2(uint256 x) internal pure returns (uint256 result) {\n // 2^192 doesn't fit within the 192.64-bit format used internally in this function.\n if (x >= 192e18) {\n revert PRBMathUD60x18__Exp2InputTooBig(x);\n }\n\n unchecked {\n // Convert x to the 192.64-bit fixed-point format.\n uint256 x192x64 = (x << 64) / SCALE;\n\n // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\n result = PRBMath.exp2(x192x64);\n }\n }\n\n /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\n /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\n /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n /// @param x The unsigned 60.18-decimal fixed-point number to floor.\n /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\n function floor(uint256 x) internal pure returns (uint256 result) {\n assembly {\n // Equivalent to \"x % SCALE\" but faster.\n let remainder := mod(x, SCALE)\n\n // Equivalent to \"x - remainder * (remainder > 0 ? 1 : 0)\" but faster.\n result := sub(x, mul(remainder, gt(remainder, 0)))\n }\n }\n\n /// @notice Yields the excess beyond the floor of x.\n /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\n /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\n /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\n function frac(uint256 x) internal pure returns (uint256 result) {\n assembly {\n result := mod(x, SCALE)\n }\n }\n\n /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\n ///\n /// @dev Requirements:\n /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\n ///\n /// @param x The basic integer to convert.\n /// @param result The same number in unsigned 60.18-decimal fixed-point representation.\n function fromUint(uint256 x) internal pure returns (uint256 result) {\n unchecked {\n if (x > MAX_UD60x18 / SCALE) {\n revert PRBMathUD60x18__FromUintOverflow(x);\n }\n result = x * SCALE;\n }\n }\n\n /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\n ///\n /// @dev Requirements:\n /// - x * y must fit within MAX_UD60x18, lest it overflows.\n ///\n /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\n /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\n if (x == 0) {\n return 0;\n }\n\n unchecked {\n // Checking for overflow this way is faster than letting Solidity do it.\n uint256 xy = x * y;\n if (xy / x != y) {\n revert PRBMathUD60x18__GmOverflow(x, y);\n }\n\n // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\n // during multiplication. See the comments within the \"sqrt\" function.\n result = PRBMath.sqrt(xy);\n }\n }\n\n /// @notice Calculates 1 / x, rounding toward zero.\n ///\n /// @dev Requirements:\n /// - x cannot be zero.\n ///\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\n /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\n function inv(uint256 x) internal pure returns (uint256 result) {\n unchecked {\n // 1e36 is SCALE * SCALE.\n result = 1e36 / x;\n }\n }\n\n /// @notice Calculates the natural logarithm of x.\n ///\n /// @dev Based on the insight that ln(x) = log2(x) / log2(e).\n ///\n /// Requirements:\n /// - All from \"log2\".\n ///\n /// Caveats:\n /// - All from \"log2\".\n /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\n ///\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\n /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\n function ln(uint256 x) internal pure returns (uint256 result) {\n // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\n // can return is 196205294292027477728.\n unchecked {\n result = (log2(x) * SCALE) / LOG2_E;\n }\n }\n\n /// @notice Calculates the common logarithm of x.\n ///\n /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common\n /// logarithm based on the insight that log10(x) = log2(x) / log2(10).\n ///\n /// Requirements:\n /// - All from \"log2\".\n ///\n /// Caveats:\n /// - All from \"log2\".\n ///\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\n /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\n function log10(uint256 x) internal pure returns (uint256 result) {\n if (x < SCALE) {\n revert PRBMathUD60x18__LogInputTooSmall(x);\n }\n\n // Note that the \"mul\" in this block is the assembly multiplication operation, not the \"mul\" function defined\n // in this contract.\n // prettier-ignore\n assembly {\n switch x\n case 1 { result := mul(SCALE, sub(0, 18)) }\n case 10 { result := mul(SCALE, sub(1, 18)) }\n case 100 { result := mul(SCALE, sub(2, 18)) }\n case 1000 { result := mul(SCALE, sub(3, 18)) }\n case 10000 { result := mul(SCALE, sub(4, 18)) }\n case 100000 { result := mul(SCALE, sub(5, 18)) }\n case 1000000 { result := mul(SCALE, sub(6, 18)) }\n case 10000000 { result := mul(SCALE, sub(7, 18)) }\n case 100000000 { result := mul(SCALE, sub(8, 18)) }\n case 1000000000 { result := mul(SCALE, sub(9, 18)) }\n case 10000000000 { result := mul(SCALE, sub(10, 18)) }\n case 100000000000 { result := mul(SCALE, sub(11, 18)) }\n case 1000000000000 { result := mul(SCALE, sub(12, 18)) }\n case 10000000000000 { result := mul(SCALE, sub(13, 18)) }\n case 100000000000000 { result := mul(SCALE, sub(14, 18)) }\n case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\n case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\n case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\n case 1000000000000000000 { result := 0 }\n case 10000000000000000000 { result := SCALE }\n case 100000000000000000000 { result := mul(SCALE, 2) }\n case 1000000000000000000000 { result := mul(SCALE, 3) }\n case 10000000000000000000000 { result := mul(SCALE, 4) }\n case 100000000000000000000000 { result := mul(SCALE, 5) }\n case 1000000000000000000000000 { result := mul(SCALE, 6) }\n case 10000000000000000000000000 { result := mul(SCALE, 7) }\n case 100000000000000000000000000 { result := mul(SCALE, 8) }\n case 1000000000000000000000000000 { result := mul(SCALE, 9) }\n case 10000000000000000000000000000 { result := mul(SCALE, 10) }\n case 100000000000000000000000000000 { result := mul(SCALE, 11) }\n case 1000000000000000000000000000000 { result := mul(SCALE, 12) }\n case 10000000000000000000000000000000 { result := mul(SCALE, 13) }\n case 100000000000000000000000000000000 { result := mul(SCALE, 14) }\n case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\n case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\n case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\n case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\n case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\n case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\n case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\n case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\n case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\n case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\n case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\n case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\n case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\n case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\n case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\n case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\n case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\n case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\n case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\n case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\n case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\n case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\n case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\n case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\n case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\n case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\n case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\n case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\n case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\n case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\n case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\n case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\n case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\n case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\n case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\n case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\n case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\n case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\n case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\n default {\n result := MAX_UD60x18\n }\n }\n\n if (result == MAX_UD60x18) {\n // Do the fixed-point division inline to save gas. The denominator is log2(10).\n unchecked {\n result = (log2(x) * SCALE) / 3_321928094887362347;\n }\n }\n }\n\n /// @notice Calculates the binary logarithm of x.\n ///\n /// @dev Based on the iterative approximation algorithm.\n /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\n ///\n /// Requirements:\n /// - x must be greater than or equal to SCALE, otherwise the result would be negative.\n ///\n /// Caveats:\n /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\n ///\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\n /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\n function log2(uint256 x) internal pure returns (uint256 result) {\n if (x < SCALE) {\n revert PRBMathUD60x18__LogInputTooSmall(x);\n }\n unchecked {\n // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\n uint256 n = PRBMath.mostSignificantBit(x / SCALE);\n\n // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow\n // because n is maximum 255 and SCALE is 1e18.\n result = n * SCALE;\n\n // This is y = x * 2^(-n).\n uint256 y = x >> n;\n\n // If y = 1, the fractional part is zero.\n if (y == SCALE) {\n return result;\n }\n\n // Calculate the fractional part via the iterative approximation.\n // The \"delta >>= 1\" part is equivalent to \"delta /= 2\", but shifting bits is faster.\n for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {\n y = (y * y) / SCALE;\n\n // Is y^2 > 2 and so in the range [2,4)?\n if (y >= 2 * SCALE) {\n // Add the 2^(-m) factor to the logarithm.\n result += delta;\n\n // Corresponds to z/2 on Wikipedia.\n y >>= 1;\n }\n }\n }\n }\n\n /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\n /// fixed-point number.\n /// @dev See the documentation for the \"PRBMath.mulDivFixedPoint\" function.\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n /// @return result The product as an unsigned 60.18-decimal fixed-point number.\n function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\n result = PRBMath.mulDivFixedPoint(x, y);\n }\n\n /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\n function pi() internal pure returns (uint256 result) {\n result = 3_141592653589793238;\n }\n\n /// @notice Raises x to the power of y.\n ///\n /// @dev Based on the insight that x^y = 2^(log2(x) * y).\n ///\n /// Requirements:\n /// - All from \"exp2\", \"log2\" and \"mul\".\n ///\n /// Caveats:\n /// - All from \"exp2\", \"log2\" and \"mul\".\n /// - Assumes 0^0 is 1.\n ///\n /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\n /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\n /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\n function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\n if (x == 0) {\n result = y == 0 ? SCALE : uint256(0);\n } else {\n result = exp2(mul(log2(x), y));\n }\n }\n\n /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\n /// famous algorithm \"exponentiation by squaring\".\n ///\n /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n ///\n /// Requirements:\n /// - The result must fit within MAX_UD60x18.\n ///\n /// Caveats:\n /// - All from \"mul\".\n /// - Assumes 0^0 is 1.\n ///\n /// @param x The base as an unsigned 60.18-decimal fixed-point number.\n /// @param y The exponent as an uint256.\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\n function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\n // Calculate the first iteration of the loop in advance.\n result = y & 1 > 0 ? x : SCALE;\n\n // Equivalent to \"for(y /= 2; y > 0; y /= 2)\" but faster.\n for (y >>= 1; y > 0; y >>= 1) {\n x = PRBMath.mulDivFixedPoint(x, x);\n\n // Equivalent to \"y % 2 == 1\" but faster.\n if (y & 1 > 0) {\n result = PRBMath.mulDivFixedPoint(result, x);\n }\n }\n }\n\n /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\n function scale() internal pure returns (uint256 result) {\n result = SCALE;\n }\n\n /// @notice Calculates the square root of x, rounding down.\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n ///\n /// Requirements:\n /// - x must be less than MAX_UD60x18 / SCALE.\n ///\n /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\n /// @return result The result as an unsigned 60.18-decimal fixed-point .\n function sqrt(uint256 x) internal pure returns (uint256 result) {\n unchecked {\n if (x > MAX_UD60x18 / SCALE) {\n revert PRBMathUD60x18__SqrtOverflow(x);\n }\n // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\n // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\n result = PRBMath.sqrt(x * SCALE);\n }\n }\n\n /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\n /// @param x The unsigned 60.18-decimal fixed-point number to convert.\n /// @return result The same number in basic integer form.\n function toUint(uint256 x) internal pure returns (uint256 result) {\n unchecked {\n result = x / SCALE;\n }\n }\n}\n" + }, + "solidity-bytes-utils/contracts/BytesLib.sol": { + "content": "// SPDX-License-Identifier: Unlicense\n/*\n * @title Solidity Bytes Arrays Utils\n * @author Gonçalo Sá \n *\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n */\npragma solidity >=0.8.0 <0.9.0;\n\n\nlibrary BytesLib {\n function concat(\n bytes memory _preBytes,\n bytes memory _postBytes\n )\n internal\n pure\n returns (bytes memory)\n {\n bytes memory tempBytes;\n\n assembly {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // Store the length of the first bytes array at the beginning of\n // the memory for tempBytes.\n let length := mload(_preBytes)\n mstore(tempBytes, length)\n\n // Maintain a memory counter for the current write location in the\n // temp bytes array by adding the 32 bytes for the array length to\n // the starting location.\n let mc := add(tempBytes, 0x20)\n // Stop copying when the memory counter reaches the length of the\n // first bytes array.\n let end := add(mc, length)\n\n for {\n // Initialize a copy counter to the start of the _preBytes data,\n // 32 bytes into its memory.\n let cc := add(_preBytes, 0x20)\n } lt(mc, end) {\n // Increase both counters by 32 bytes each iteration.\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // Write the _preBytes data into the tempBytes memory 32 bytes\n // at a time.\n mstore(mc, mload(cc))\n }\n\n // Add the length of _postBytes to the current length of tempBytes\n // and store it as the new length in the first 32 bytes of the\n // tempBytes memory.\n length := mload(_postBytes)\n mstore(tempBytes, add(length, mload(tempBytes)))\n\n // Move the memory counter back from a multiple of 0x20 to the\n // actual end of the _preBytes data.\n mc := end\n // Stop copying when the memory counter reaches the new combined\n // length of the arrays.\n end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n // Update the free-memory pointer by padding our last write location\n // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n // next 32 byte block, then round down to the nearest multiple of\n // 32. If the sum of the length of the two arrays is zero then add\n // one before rounding down to leave a blank 32 bytes (the length block with 0).\n mstore(0x40, and(\n add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n not(31) // Round down to the nearest 32 bytes.\n ))\n }\n\n return tempBytes;\n }\n\n function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n assembly {\n // Read the first 32 bytes of _preBytes storage, which is the length\n // of the array. (We don't need to use the offset into the slot\n // because arrays use the entire slot.)\n let fslot := sload(_preBytes.slot)\n // Arrays of 31 bytes or less have an even value in their slot,\n // while longer arrays have an odd value. The actual length is\n // the slot divided by two for odd values, and the lowest order\n // byte divided by two for even values.\n // If the slot is even, bitwise and the slot with 255 and divide by\n // two to get the length. If the slot is odd, bitwise and the slot\n // with -1 and divide by two.\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n let newlength := add(slength, mlength)\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n switch add(lt(slength, 32), lt(newlength, 32))\n case 2 {\n // Since the new array still fits in the slot, we just need to\n // update the contents of the slot.\n // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n sstore(\n _preBytes.slot,\n // all the modifications to the slot are inside this\n // next block\n add(\n // we can just add to the slot contents because the\n // bytes we want to change are the LSBs\n fslot,\n add(\n mul(\n div(\n // load the bytes from memory\n mload(add(_postBytes, 0x20)),\n // zero all bytes to the right\n exp(0x100, sub(32, mlength))\n ),\n // and now shift left the number of bytes to\n // leave space for the length in the slot\n exp(0x100, sub(32, newlength))\n ),\n // increase length by the double of the memory\n // bytes length\n mul(mlength, 2)\n )\n )\n )\n }\n case 1 {\n // The stored value fits in the slot, but the combined value\n // will exceed it.\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // The contents of the _postBytes array start 32 bytes into\n // the structure. Our first read should obtain the `submod`\n // bytes that can fit into the unused space in the last word\n // of the stored array. To get this, we read 32 bytes starting\n // from `submod`, so the data we read overlaps with the array\n // contents by `submod` bytes. Masking the lowest-order\n // `submod` bytes allows us to add that value directly to the\n // stored value.\n\n let submod := sub(32, slength)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(\n sc,\n add(\n and(\n fslot,\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00\n ),\n and(mload(mc), mask)\n )\n )\n\n for {\n mc := add(mc, 0x20)\n sc := add(sc, 1)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n default {\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n // Start copying to the last used word of the stored array.\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // Copy over the first `submod` bytes of the new data as in\n // case 1 above.\n let slengthmod := mod(slength, 32)\n let mlengthmod := mod(mlength, 32)\n let submod := sub(32, slengthmod)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n for {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n }\n }\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n )\n internal\n pure\n returns (bytes memory)\n {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n require(_bytes.length >= _start + 20, \"toAddress_outOfBounds\");\n address tempAddress;\n\n assembly {\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n }\n\n return tempAddress;\n }\n\n function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n require(_bytes.length >= _start + 1 , \"toUint8_outOfBounds\");\n uint8 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x1), _start))\n }\n\n return tempUint;\n }\n\n function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n require(_bytes.length >= _start + 2, \"toUint16_outOfBounds\");\n uint16 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x2), _start))\n }\n\n return tempUint;\n }\n\n function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n require(_bytes.length >= _start + 4, \"toUint32_outOfBounds\");\n uint32 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x4), _start))\n }\n\n return tempUint;\n }\n\n function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n require(_bytes.length >= _start + 8, \"toUint64_outOfBounds\");\n uint64 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x8), _start))\n }\n\n return tempUint;\n }\n\n function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n require(_bytes.length >= _start + 12, \"toUint96_outOfBounds\");\n uint96 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0xc), _start))\n }\n\n return tempUint;\n }\n\n function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n require(_bytes.length >= _start + 16, \"toUint128_outOfBounds\");\n uint128 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x10), _start))\n }\n\n return tempUint;\n }\n\n function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n require(_bytes.length >= _start + 32, \"toUint256_outOfBounds\");\n uint256 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempUint;\n }\n\n function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n require(_bytes.length >= _start + 32, \"toBytes32_outOfBounds\");\n bytes32 tempBytes32;\n\n assembly {\n tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempBytes32;\n }\n\n function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n bool success = true;\n\n assembly {\n let length := mload(_preBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(length, mload(_postBytes))\n case 1 {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n let mc := add(_preBytes, 0x20)\n let end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n } eq(add(lt(mc, end), cb), 2) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // if any of these checks fails then arrays are not equal\n if iszero(eq(mload(mc), mload(cc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n\n function equalStorage(\n bytes storage _preBytes,\n bytes memory _postBytes\n )\n internal\n view\n returns (bool)\n {\n bool success = true;\n\n assembly {\n // we know _preBytes_offset is 0\n let fslot := sload(_preBytes.slot)\n // Decode the length of the stored array like in concatStorage().\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(slength, mlength)\n case 1 {\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n if iszero(iszero(slength)) {\n switch lt(slength, 32)\n case 1 {\n // blank the last byte which is the length\n fslot := mul(div(fslot, 0x100), 0x100)\n\n if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n // unsuccess:\n success := 0\n }\n }\n default {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := keccak256(0x0, 0x20)\n\n let mc := add(_postBytes, 0x20)\n let end := add(mc, mlength)\n\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n for {} eq(add(lt(mc, end), cb), 2) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n if iszero(eq(sload(sc), mload(mc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10, + "details": { + "constantOptimizer": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index b2af3ef9a..9950b7ca2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,7 +18,7 @@ The documentation is generated from the deployment artifacts in `/deployments/` | Network | Contracts | Documentation | Last Updated | |---------|-----------|---------------|-------------| -| Arbitrum One | 132 | [View](./arbitrum-deployments.md) | Aug 13, 2025, 07:17 AM UTC | +| Arbitrum One | 133 | [View](./arbitrum-deployments.md) | Oct 17, 2025, 03:59 AM UTC | | Avalanche C-Chain | 131 | [View](./avalanche-deployments.md) | Aug 13, 2025, 07:17 AM UTC | | Botanix | 127 | [View](./botanix-deployments.md) | Aug 13, 2025, 07:17 AM UTC | diff --git a/docs/arbitrum-deployments.md b/docs/arbitrum-deployments.md index ee1b3146d..956864b2a 100644 --- a/docs/arbitrum-deployments.md +++ b/docs/arbitrum-deployments.md @@ -2,8 +2,8 @@ **Network Type:** Mainnet **Chain ID:** 42161 -**Total Contracts:** 132 -**Last Updated:** Aug 13, 2025, 07:17 AM UTC +**Total Contracts:** 133 +**Last Updated:** Oct 17, 2025, 03:59 AM UTC ## Deployed Contracts @@ -23,8 +23,9 @@ | ClaimVault | `0x6a5771a57445400c00a8656C34ECC309996657e4` | [View on Explorer](https://arbiscan.io/address/0x6a5771a57445400c00a8656C34ECC309996657e4) | | Config | `0x1d3dbe2F913dcA27E943b2837A4Cdad6653B02E2` | [View on Explorer](https://arbiscan.io/address/0x1d3dbe2F913dcA27E943b2837A4Cdad6653B02E2) | | ConfigSyncer | `0xd41e09434CDFe20ceA9411f55D86dDb314b6Af94` | [View on Explorer](https://arbiscan.io/address/0xd41e09434CDFe20ceA9411f55D86dDb314b6Af94) | -| ConfigTimelockController | `0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621` | [View on Explorer](https://arbiscan.io/address/0x8c6e20A2211D1b70cD7c0789EcE44fDB19567621) | +| ConfigTimelockController | `0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f` | [View on Explorer](https://arbiscan.io/address/0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f) | | ConfigUtils | `0x4a39c37c292D8ba23c7a35AE7C10AD8b2da21b3b` | [View on Explorer](https://arbiscan.io/address/0x4a39c37c292D8ba23c7a35AE7C10AD8b2da21b3b) | +| ContributorHandler | `0x4729D9f61c0159F5e02D2C2e5937B3225e55442C` | [View on Explorer](https://arbiscan.io/address/0x4729D9f61c0159F5e02D2C2e5937B3225e55442C) | | DataStore | `0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8` | [View on Explorer](https://arbiscan.io/address/0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8) | | DecreaseOrderExecutor | `0x3F4ee93723C2F14eeC5a44a2Cb66edA006A171fd` | [View on Explorer](https://arbiscan.io/address/0x3F4ee93723C2F14eeC5a44a2Cb66edA006A171fd) | | DecreaseOrderUtils | `0xe4BcceaFF011Ac04Aa0318AfE85E2739bBa99517` | [View on Explorer](https://arbiscan.io/address/0xe4BcceaFF011Ac04Aa0318AfE85E2739bBa99517) | @@ -79,10 +80,10 @@ | LayerZeroProvider | `0x7129Ea01F0826c705d6F7ab01Cf3C06bb83E9397` | [View on Explorer](https://arbiscan.io/address/0x7129Ea01F0826c705d6F7ab01Cf3C06bb83E9397) | | LiquidationHandler | `0xdFc557EdF817bCd69F3b82d54f6338ecad2667CA` | [View on Explorer](https://arbiscan.io/address/0xdFc557EdF817bCd69F3b82d54f6338ecad2667CA) | | LiquidationUtils | `0x78AACD5FA15852cb1B11cDA1C968a98971CD519a` | [View on Explorer](https://arbiscan.io/address/0x78AACD5FA15852cb1B11cDA1C968a98971CD519a) | -| MarketEventUtils | `0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8` | [View on Explorer](https://arbiscan.io/address/0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8) | +| MarketEventUtils | `0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8` | [View on Explorer](https://arbiscan.io/address/0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8) | | MarketFactory | `0xf5F30B10141E1F63FC11eD772931A8294a591996` | [View on Explorer](https://arbiscan.io/address/0xf5F30B10141E1F63FC11eD772931A8294a591996) | -| MarketStoreUtils | `0xd727120ac811e9136D4a5D5C6219aEE37e275785` | [View on Explorer](https://arbiscan.io/address/0xd727120ac811e9136D4a5D5C6219aEE37e275785) | -| MarketUtils | `0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96` | [View on Explorer](https://arbiscan.io/address/0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96) | +| MarketStoreUtils | `0x2e5D10A48C00cFcc6A31af873118d739323Ff71B` | [View on Explorer](https://arbiscan.io/address/0x2e5D10A48C00cFcc6A31af873118d739323Ff71B) | +| MarketUtils | `0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB` | [View on Explorer](https://arbiscan.io/address/0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB) | | MockPriceFeed | `0x2e29aE5474588C79C2C1169D7e7BBB5db6A607c0` | [View on Explorer](https://arbiscan.io/address/0x2e29aE5474588C79C2C1169D7e7BBB5db6A607c0) | | Multicall3 | `0xe79118d6D92a4b23369ba356C90b9A7ABf1CB961` | [View on Explorer](https://arbiscan.io/address/0xe79118d6D92a4b23369ba356C90b9A7ABf1CB961) | | MultichainClaimsRouter | `0x2A7244EE5373D2F161cE99F0D144c12860D651Af` | [View on Explorer](https://arbiscan.io/address/0x2A7244EE5373D2F161cE99F0D144c12860D651Af) | @@ -102,10 +103,10 @@ | OrderUtils | `0x459058505A7c7252efE93aa69D03F6198601DA9e` | [View on Explorer](https://arbiscan.io/address/0x459058505A7c7252efE93aa69D03F6198601DA9e) | | OrderVault | `0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5` | [View on Explorer](https://arbiscan.io/address/0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5) | | PositionEventUtils | `0x07F8Aba575B987a7165bDAcA727C74C1ccDEC258` | [View on Explorer](https://arbiscan.io/address/0x07F8Aba575B987a7165bDAcA727C74C1ccDEC258) | -| PositionImpactPoolUtils | `0x87a0d100b4F9b2A53353974c3596eEC33de8060f` | [View on Explorer](https://arbiscan.io/address/0x87a0d100b4F9b2A53353974c3596eEC33de8060f) | -| PositionPricingUtils | `0x984Eada4e97CDA510B48BB654A216d3ad47bA362` | [View on Explorer](https://arbiscan.io/address/0x984Eada4e97CDA510B48BB654A216d3ad47bA362) | +| PositionImpactPoolUtils | `0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3` | [View on Explorer](https://arbiscan.io/address/0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3) | +| PositionPricingUtils | `0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4` | [View on Explorer](https://arbiscan.io/address/0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4) | | PositionStoreUtils | `0x065799d0AF51eF81686A641d4e5A58A0B8186E3E` | [View on Explorer](https://arbiscan.io/address/0x065799d0AF51eF81686A641d4e5A58A0B8186E3E) | -| PositionUtils | `0xf718aE0025504577b18f8773e56986B6e29C819F` | [View on Explorer](https://arbiscan.io/address/0xf718aE0025504577b18f8773e56986B6e29C819F) | +| PositionUtils | `0x58b09FD12863218F2ca156808C2Ae48aaCD0c072` | [View on Explorer](https://arbiscan.io/address/0x58b09FD12863218F2ca156808C2Ae48aaCD0c072) | | Printer | `0xcdF1ffdfdf74CcC667227F53681E907De48F5156` | [View on Explorer](https://arbiscan.io/address/0xcdF1ffdfdf74CcC667227F53681E907De48F5156) | | ProtocolGovernor | `0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68` | [View on Explorer](https://arbiscan.io/address/0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68) | | Reader | `0x65A6CC451BAfF7e7B4FDAb4157763aB4b6b44D0E` | [View on Explorer](https://arbiscan.io/address/0x65A6CC451BAfF7e7B4FDAb4157763aB4b6b44D0E) | @@ -134,7 +135,7 @@ | SwapPricingUtils | `0x08F96361d3D67e107ECf968bf0cf706F706Ba7FA` | [View on Explorer](https://arbiscan.io/address/0x08F96361d3D67e107ECf968bf0cf706F706Ba7FA) | | SwapUtils | `0xFEd5437cb65f06187b41fb05b1C2D0E9ed2Fc549` | [View on Explorer](https://arbiscan.io/address/0xFEd5437cb65f06187b41fb05b1C2D0E9ed2Fc549) | | Timelock | `0x7A967D114B8676874FA2cFC1C14F3095C88418Eb` | [View on Explorer](https://arbiscan.io/address/0x7A967D114B8676874FA2cFC1C14F3095C88418Eb) | -| TimelockConfig | `0xC181eB022F33b8ba808AD96348B03e8A753A859b` | [View on Explorer](https://arbiscan.io/address/0xC181eB022F33b8ba808AD96348B03e8A753A859b) | +| TimelockConfig | `0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1` | [View on Explorer](https://arbiscan.io/address/0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1) | | TimestampInitializer | `0x1e72F7C6198C3DF7CA7f12173B3EBeBb46434960` | [View on Explorer](https://arbiscan.io/address/0x1e72F7C6198C3DF7CA7f12173B3EBeBb46434960) | | WithdrawalEventUtils | `0x7B82a3fB00363a877EE247D52FD2c7Aa01ECcd2e` | [View on Explorer](https://arbiscan.io/address/0x7B82a3fB00363a877EE247D52FD2c7Aa01ECcd2e) | | WithdrawalHandler | `0x1EC018d2b6ACCA20a0bEDb86450b7E27D1D8355B` | [View on Explorer](https://arbiscan.io/address/0x1EC018d2b6ACCA20a0bEDb86450b7E27D1D8355B) | diff --git a/hardhat.config.ts b/hardhat.config.ts index 38ef9c5ca..30df7610d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -35,6 +35,7 @@ import { deleteFile, writeJsonFile } from "./utils/file"; import { TASK_VERIFY } from "@nomicfoundation/hardhat-verify/internal/task-names"; const getNetworkFromCLI = () => { + if (process.env.HARDHAT_NETWORK) return process.env.HARDHAT_NETWORK; const i = process.argv.indexOf("--network"); return i !== -1 && process.argv[i + 1] ? process.argv[i + 1] : "hardhat"; }; diff --git a/scripts/cache/verification/arbitrum-api.etherscan.io.json b/scripts/cache/verification/arbitrum-api.etherscan.io.json index 1024a4461..f65182df4 100644 --- a/scripts/cache/verification/arbitrum-api.etherscan.io.json +++ b/scripts/cache/verification/arbitrum-api.etherscan.io.json @@ -1 +1 @@ -{"0x7548914962E776e6DB3464cfEa4732165144163B":true,"0x83af390a8f92028FA221D1FaD20F06aB7121A100":true,"0x9F6a6D96cEA1C6bCD58e074FF2590855EEa02589":true,"0xAc85Af4295D5Ee41eEf325432619b13Aa9F15E25":true,"0x1b213E2fFDA3f68ee9533EC3493e291DDE14325f":true,"0xE1D7613BA30E2853Cf158b58FbDA618ec6a1Dd71":true,"0xBA682243c478Ebd7D7Cd67d2ea7D25928A8C16f9":true,"0xc196Dd186Fd6A62c7d98D45C566d44Cc4745583D":true,"0xB9089f9b862db6B591cC54A2D12c1FBAcf0bf834":true,"0x0913CA02B93A2AA381a420AEac38490ee6284A32":true,"0x28f1F4AA95F49FAB62464536A269437B13d48976":true,"0x6a5771a57445400c00a8656C34ECC309996657e4":true,"0x1d3dbe2F913dcA27E943b2837A4Cdad6653B02E2":true,"0xd41e09434CDFe20ceA9411f55D86dDb314b6Af94":true,"0xeF7463039E1116f875AD72fA567e91511D6A8F5E":true,"0x4a39c37c292D8ba23c7a35AE7C10AD8b2da21b3b":true,"0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8":true,"0x3F4ee93723C2F14eeC5a44a2Cb66edA006A171fd":true,"0xe4BcceaFF011Ac04Aa0318AfE85E2739bBa99517":true,"0x02176D8560f0596F67C2D10133F07b635602A168":true,"0x46c4D94FC6eba08d38e51F12d618c0aB3b1B5Fdf":true,"0x0AF4d7c87339d3A4b40233439A4aBE13d97007f9":true,"0x7F8E623645Db03a00D7b71896322c8796b1208da":true,"0x2571197BbEA0547477eDde419CF910802Dfc583f":true,"0x2C4f39fe8F558d84811E875aaf0903BA86bebb1b":true,"0x833bdF7B050D2a55045f964540376E0dcA264936":true,"0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55":true,"0xf7f8FbF59d6b7318CB5d3B023AD4196Fa16dc723":true,"0x97b2Fd0D630eaC2c24359e6fE00A15840c89d259":true,"0xC8ee91A54287DB53897056e12D9819156D3822Fb":true,"0xa1b7693222eB522D847A756F440A7c34937344E0":true,"0xA010c887a6ADFbedA7D4bd1Bb973c48866042512":true,"0x834bd4c8e48f32cf9d9EEE1AC6974d5C8F823a5C":true,"0x74bfc9c1E496D96bbAF87A8231aAD1c79DDbf7bA":true,"0x8A6796CC014d15be4ddd19772e2048A661763e70":true,"0x389CEf541397e872dC04421f166B5Bc2E0b374a5":true,"0x7EB417637a3E6d1C19E6d69158c47610b7a5d9B3":true,"0xE7Ab34574296CF6a8d3F4cD7Bf45311146d225f7":true,"0xfaa2433563a26Df5A816AE4155155e3b5Ad15839":true,"0x49eaEAfa626011EDe0B9852e567DfCF8b62Aba88":true,"0x72d9Ee15220BC28A8b0dfa30Ef3F671b03Df274e":true,"0x6eAae2bdA93696DA9f9C6354b738e60249f4aa75":true,"0xa921e1D196FBA06022Bc2C3A145aDaDaa4EeA6D1":true,"0xFedDB63759f275061Ce088F51caff727Fd782401":true,"0x14D2122F604C61f846C015D30efe5ccB44f06FFA":true,"0xA02fdDf5476eA41151BF97055C487D9258b7dF3D":true,"0xdaFa7Deb67805d7498Aa926002bB2d713D1d9256":true,"0x3f6dF0c3A7221BA1375E87e7097885a601B41Afc":true,"0xb51e34dc3A7c80E4ABbC3800aD0e487b7b878339":true,"0x0F012e736e63eAb4e326595055a33279633DaA93":true,"0x68d2ac7b931939471245B8E7197eCaF33aE855B4":true,"0x372aaDF1921c6f92346a4D5E9E5186bd00fF0562":true,"0xfa1EEE289c9006595FD0911e2ffcBFD6Db0914d4":true,"0x7FfedCAC2eCb2C29dDc027B60D6F8107295Ff2eA":true,"0x35dF0D75603dAdf745D3374476DE3bE715f99956":true,"0xf7A3A2E5b33fD0f66BAa26c4e9cbF5Df91F350D6":true,"0x393053B58f9678C9c28c2cE941fF6cac49C3F8f9":true,"0xE5835c5b135eB770f8B10Fa4F4cDAbcA11841382":true,"0x694714CcDaFf7ff13E1b9E2c68C324ef1B95E965":true,"0xb013BB9C60C5EBe017FAb08889869aeC3635Ff8F":true,"0x605129e6aCff81e424313AAff7Fa94F6a91ab1FF":true,"0x5d6B84086DA6d4B0b6C0dF7E02f8a6A039226530":true,"0xFBEff82f2DD5E51B8AF34b57cf788b4b09d466F9":true,"0x2A29D3a792000750807cc401806d6fd539928481":true,"0x1DAa9A375132a3cDe9133B0a5DA67B57Ef21d102":true,"0x62e274d631F7705c17c1Bf6dF0971Cabaa1D0B47":true,"0xb81b09580B06F31b911e34ec80983ee8b2e68580":true,"0x70a21A5B6D191DcAA4A1F1964e7D947eDF95ABD3":true,"0xD4BbE0fc95FEb69400C47F05b86a7d1B63272fAB":true,"0x78AACD5FA15852cb1B11cDA1C968a98971CD519a":true,"0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8":true,"0xf5F30B10141E1F63FC11eD772931A8294a591996":true,"0xd727120ac811e9136D4a5D5C6219aEE37e275785":true,"0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96":true,"0x2e29aE5474588C79C2C1169D7e7BBB5db6A607c0":true,"0xe79118d6D92a4b23369ba356C90b9A7ABf1CB961":true,"0x529C80A39f71Ed70A964E700827B529142A1FA8d":true,"0xACfFe89487495C175C7D517105dF5949504fdC03":true,"0x707E86926cfDb526f023308898d1915a87D23205":true,"0x2bE05D69c59b0F7aaE0c6E955A5F9a52aCA6a4a8":true,"0x76bf0940cc05AEB968919dB5B0f1759726bFC7dB":true,"0x4B3251Fe0f0502DB4Fe5caa6B7f14eB5D2ae3ab3":true,"0x1158E639Da58FD104908343ef3F42A79d54D2918":true,"0xCeaadFAf6A8C489B250e407987877c5fDfcDBE6E":true,"0x6D5F3c723002847B009D07Fe8e17d6958F153E4e":true,"0x2e246061BE08DC56d33E03Dc0cb962C2155722b5":true,"0xA8AF9B86fC47deAde1bc66B12673706615E2B011":true,"0xA421Fa4581b37CAE2E43502D205460a57B7D7a4b":true,"0x6CCd77F770E7213C584fF8bfbf47C7A0BdA30665":true,"0x29B7Cf4831288932De48C929cB09649d1c6cA69d":true,"0x459058505A7c7252efE93aa69D03F6198601DA9e":true,"0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5":true,"0x07F8Aba575B987a7165bDAcA727C74C1ccDEC258":true,"0x87a0d100b4F9b2A53353974c3596eEC33de8060f":true,"0x984Eada4e97CDA510B48BB654A216d3ad47bA362":true,"0x065799d0AF51eF81686A641d4e5A58A0B8186E3E":true,"0xf718aE0025504577b18f8773e56986B6e29C819F":true,"0xcdF1ffdfdf74CcC667227F53681E907De48F5156":true,"0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68":true,"0x65A6CC451BAfF7e7B4FDAb4157763aB4b6b44D0E":true,"0x698ef7eb7A46458e1f9B9181354955809baD5A6F":true,"0x12Ac77003B3D11b0853d1FD12E5AF22a9060eC4b":true,"0x60dFa6974A1C3a45918b6B4E6F365fcc2222DF7e":true,"0x1e6E449F4052dB43eDbDa8B7b9c82a489a5a1550":true,"0x78AB7190972DDf75f54ccf468bB2178210A67194":true,"0xfd57881C34b6Fc77197254AA95ee70B203A9F8c3":true,"0xcb25512d99F99DCf55D5FFAf300FB9Ab0a70268a":true,"0xC72390b4B667a0CB378B2DD85cFbF7Bd61593B10":true,"0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72":true,"0x7452c558d45f8afC8c83dAe62C3f8A5BE19c71f6":true,"0xfe845699777Be68f23cc81f58E48d6b59CB03aD6":true,"0x8b28a7a084D809Bbfe6B49aDdB1890aFBbae6E51":true,"0x7EA79eAC0009f7888B6f8dCFFFa1eA9AA8c30f7D":true,"0x41E1D594a9fCF6d2eA17D284C6F44C24b303aeAe":true,"0xfe99609C4AA83ff6816b64563Bdffd7fa68753Ab":true,"0x56Bd17a72cDBb15D9eb3600D7E8F22B0e8220C82":true,"0x1258AB791230412Dc862CE0cA46f2bF307386D03":true,"0xABA795147526A516Fba58F6733D84EBc61Cef427":true,"0x78E33740994201507334a20D9C05ec437AaCBc6A":true,"0xDb2AB9566732710d02b23325F79A8832118b97c5":true,"0x455D555350D5CcCD1E3Eb3D563B411Ef24697050":true,"0x24F52966Fc663b3e206f0DCbD40b6FF2df567880":true,"0x08F96361d3D67e107ECf968bf0cf706F706Ba7FA":true,"0xFEd5437cb65f06187b41fb05b1C2D0E9ed2Fc549":true,"0x7A967D114B8676874FA2cFC1C14F3095C88418Eb":true,"0x902826eeBc07eC37B077e28De1068aADd0F10a7F":true,"0x1e72F7C6198C3DF7CA7f12173B3EBeBb46434960":true,"0x7B82a3fB00363a877EE247D52FD2c7Aa01ECcd2e":true,"0xa82b86EA8db3E60287D674Cc800D961608245089":true,"0xc7Cc50BA99b7c07C09BEEFA1cCdb9259b342c66D":true,"0xCf24665fD6E38CeBEC4987D7682c69a3a0042DCf":true,"0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55":true,"0xE1d5a068c5b75E0c7Ea1A9Fe8EA056f9356C6fFD":true,"0x38B8dB61b724b51e42A88Cb8eC564CD685a0f53B":true,"0x7F01614cA5198Ec979B1aAd1DAF0DE7e0a215BDF":true} \ No newline at end of file +{"0x7548914962E776e6DB3464cfEa4732165144163B":true,"0x83af390a8f92028FA221D1FaD20F06aB7121A100":true,"0x9F6a6D96cEA1C6bCD58e074FF2590855EEa02589":true,"0xAc85Af4295D5Ee41eEf325432619b13Aa9F15E25":true,"0x1b213E2fFDA3f68ee9533EC3493e291DDE14325f":true,"0xE1D7613BA30E2853Cf158b58FbDA618ec6a1Dd71":true,"0xBA682243c478Ebd7D7Cd67d2ea7D25928A8C16f9":true,"0xc196Dd186Fd6A62c7d98D45C566d44Cc4745583D":true,"0xB9089f9b862db6B591cC54A2D12c1FBAcf0bf834":true,"0x0913CA02B93A2AA381a420AEac38490ee6284A32":true,"0x28f1F4AA95F49FAB62464536A269437B13d48976":true,"0x6a5771a57445400c00a8656C34ECC309996657e4":true,"0x1d3dbe2F913dcA27E943b2837A4Cdad6653B02E2":true,"0xd41e09434CDFe20ceA9411f55D86dDb314b6Af94":true,"0xeF7463039E1116f875AD72fA567e91511D6A8F5E":true,"0x4a39c37c292D8ba23c7a35AE7C10AD8b2da21b3b":true,"0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8":true,"0x3F4ee93723C2F14eeC5a44a2Cb66edA006A171fd":true,"0xe4BcceaFF011Ac04Aa0318AfE85E2739bBa99517":true,"0x02176D8560f0596F67C2D10133F07b635602A168":true,"0x46c4D94FC6eba08d38e51F12d618c0aB3b1B5Fdf":true,"0x0AF4d7c87339d3A4b40233439A4aBE13d97007f9":true,"0x7F8E623645Db03a00D7b71896322c8796b1208da":true,"0x2571197BbEA0547477eDde419CF910802Dfc583f":true,"0x2C4f39fe8F558d84811E875aaf0903BA86bebb1b":true,"0x833bdF7B050D2a55045f964540376E0dcA264936":true,"0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55":true,"0xf7f8FbF59d6b7318CB5d3B023AD4196Fa16dc723":true,"0x97b2Fd0D630eaC2c24359e6fE00A15840c89d259":true,"0xC8ee91A54287DB53897056e12D9819156D3822Fb":true,"0xa1b7693222eB522D847A756F440A7c34937344E0":true,"0xA010c887a6ADFbedA7D4bd1Bb973c48866042512":true,"0x834bd4c8e48f32cf9d9EEE1AC6974d5C8F823a5C":true,"0x74bfc9c1E496D96bbAF87A8231aAD1c79DDbf7bA":true,"0x8A6796CC014d15be4ddd19772e2048A661763e70":true,"0x389CEf541397e872dC04421f166B5Bc2E0b374a5":true,"0x7EB417637a3E6d1C19E6d69158c47610b7a5d9B3":true,"0xE7Ab34574296CF6a8d3F4cD7Bf45311146d225f7":true,"0xfaa2433563a26Df5A816AE4155155e3b5Ad15839":true,"0x49eaEAfa626011EDe0B9852e567DfCF8b62Aba88":true,"0x72d9Ee15220BC28A8b0dfa30Ef3F671b03Df274e":true,"0x6eAae2bdA93696DA9f9C6354b738e60249f4aa75":true,"0xa921e1D196FBA06022Bc2C3A145aDaDaa4EeA6D1":true,"0xFedDB63759f275061Ce088F51caff727Fd782401":true,"0x14D2122F604C61f846C015D30efe5ccB44f06FFA":true,"0xA02fdDf5476eA41151BF97055C487D9258b7dF3D":true,"0xdaFa7Deb67805d7498Aa926002bB2d713D1d9256":true,"0x3f6dF0c3A7221BA1375E87e7097885a601B41Afc":true,"0xb51e34dc3A7c80E4ABbC3800aD0e487b7b878339":true,"0x0F012e736e63eAb4e326595055a33279633DaA93":true,"0x68d2ac7b931939471245B8E7197eCaF33aE855B4":true,"0x372aaDF1921c6f92346a4D5E9E5186bd00fF0562":true,"0xfa1EEE289c9006595FD0911e2ffcBFD6Db0914d4":true,"0x7FfedCAC2eCb2C29dDc027B60D6F8107295Ff2eA":true,"0x35dF0D75603dAdf745D3374476DE3bE715f99956":true,"0xf7A3A2E5b33fD0f66BAa26c4e9cbF5Df91F350D6":true,"0x393053B58f9678C9c28c2cE941fF6cac49C3F8f9":true,"0xE5835c5b135eB770f8B10Fa4F4cDAbcA11841382":true,"0x694714CcDaFf7ff13E1b9E2c68C324ef1B95E965":true,"0xb013BB9C60C5EBe017FAb08889869aeC3635Ff8F":true,"0x605129e6aCff81e424313AAff7Fa94F6a91ab1FF":true,"0x5d6B84086DA6d4B0b6C0dF7E02f8a6A039226530":true,"0xFBEff82f2DD5E51B8AF34b57cf788b4b09d466F9":true,"0x2A29D3a792000750807cc401806d6fd539928481":true,"0x1DAa9A375132a3cDe9133B0a5DA67B57Ef21d102":true,"0x62e274d631F7705c17c1Bf6dF0971Cabaa1D0B47":true,"0xb81b09580B06F31b911e34ec80983ee8b2e68580":true,"0x70a21A5B6D191DcAA4A1F1964e7D947eDF95ABD3":true,"0xD4BbE0fc95FEb69400C47F05b86a7d1B63272fAB":true,"0x78AACD5FA15852cb1B11cDA1C968a98971CD519a":true,"0xC1bd1ad41cda5C5c5953766CbA5c375c85407cc8":true,"0xf5F30B10141E1F63FC11eD772931A8294a591996":true,"0xd727120ac811e9136D4a5D5C6219aEE37e275785":true,"0xF62E9Cfa1ffD446E3516dC2F19f2818911Bf7d96":true,"0x2e29aE5474588C79C2C1169D7e7BBB5db6A607c0":true,"0xe79118d6D92a4b23369ba356C90b9A7ABf1CB961":true,"0x529C80A39f71Ed70A964E700827B529142A1FA8d":true,"0xACfFe89487495C175C7D517105dF5949504fdC03":true,"0x707E86926cfDb526f023308898d1915a87D23205":true,"0x2bE05D69c59b0F7aaE0c6E955A5F9a52aCA6a4a8":true,"0x76bf0940cc05AEB968919dB5B0f1759726bFC7dB":true,"0x4B3251Fe0f0502DB4Fe5caa6B7f14eB5D2ae3ab3":true,"0x1158E639Da58FD104908343ef3F42A79d54D2918":true,"0xCeaadFAf6A8C489B250e407987877c5fDfcDBE6E":true,"0x6D5F3c723002847B009D07Fe8e17d6958F153E4e":true,"0x2e246061BE08DC56d33E03Dc0cb962C2155722b5":true,"0xA8AF9B86fC47deAde1bc66B12673706615E2B011":true,"0xA421Fa4581b37CAE2E43502D205460a57B7D7a4b":true,"0x6CCd77F770E7213C584fF8bfbf47C7A0BdA30665":true,"0x29B7Cf4831288932De48C929cB09649d1c6cA69d":true,"0x459058505A7c7252efE93aa69D03F6198601DA9e":true,"0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5":true,"0x07F8Aba575B987a7165bDAcA727C74C1ccDEC258":true,"0x87a0d100b4F9b2A53353974c3596eEC33de8060f":true,"0x984Eada4e97CDA510B48BB654A216d3ad47bA362":true,"0x065799d0AF51eF81686A641d4e5A58A0B8186E3E":true,"0xf718aE0025504577b18f8773e56986B6e29C819F":true,"0xcdF1ffdfdf74CcC667227F53681E907De48F5156":true,"0x03e8f708e9C85EDCEaa6AD7Cd06824CeB82A7E68":true,"0x65A6CC451BAfF7e7B4FDAb4157763aB4b6b44D0E":true,"0x698ef7eb7A46458e1f9B9181354955809baD5A6F":true,"0x12Ac77003B3D11b0853d1FD12E5AF22a9060eC4b":true,"0x60dFa6974A1C3a45918b6B4E6F365fcc2222DF7e":true,"0x1e6E449F4052dB43eDbDa8B7b9c82a489a5a1550":true,"0x78AB7190972DDf75f54ccf468bB2178210A67194":true,"0xfd57881C34b6Fc77197254AA95ee70B203A9F8c3":true,"0xcb25512d99F99DCf55D5FFAf300FB9Ab0a70268a":true,"0xC72390b4B667a0CB378B2DD85cFbF7Bd61593B10":true,"0x3c3d99FD298f679DBC2CEcd132b4eC4d0F5e6e72":true,"0x7452c558d45f8afC8c83dAe62C3f8A5BE19c71f6":true,"0xfe845699777Be68f23cc81f58E48d6b59CB03aD6":true,"0x8b28a7a084D809Bbfe6B49aDdB1890aFBbae6E51":true,"0x7EA79eAC0009f7888B6f8dCFFFa1eA9AA8c30f7D":true,"0x41E1D594a9fCF6d2eA17D284C6F44C24b303aeAe":true,"0xfe99609C4AA83ff6816b64563Bdffd7fa68753Ab":true,"0x56Bd17a72cDBb15D9eb3600D7E8F22B0e8220C82":true,"0x1258AB791230412Dc862CE0cA46f2bF307386D03":true,"0xABA795147526A516Fba58F6733D84EBc61Cef427":true,"0x78E33740994201507334a20D9C05ec437AaCBc6A":true,"0xDb2AB9566732710d02b23325F79A8832118b97c5":true,"0x455D555350D5CcCD1E3Eb3D563B411Ef24697050":true,"0x24F52966Fc663b3e206f0DCbD40b6FF2df567880":true,"0x08F96361d3D67e107ECf968bf0cf706F706Ba7FA":true,"0xFEd5437cb65f06187b41fb05b1C2D0E9ed2Fc549":true,"0x7A967D114B8676874FA2cFC1C14F3095C88418Eb":true,"0x902826eeBc07eC37B077e28De1068aADd0F10a7F":true,"0x1e72F7C6198C3DF7CA7f12173B3EBeBb46434960":true,"0x7B82a3fB00363a877EE247D52FD2c7Aa01ECcd2e":true,"0xa82b86EA8db3E60287D674Cc800D961608245089":true,"0xc7Cc50BA99b7c07C09BEEFA1cCdb9259b342c66D":true,"0xCf24665fD6E38CeBEC4987D7682c69a3a0042DCf":true,"0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55":true,"0xE1d5a068c5b75E0c7Ea1A9Fe8EA056f9356C6fFD":true,"0x38B8dB61b724b51e42A88Cb8eC564CD685a0f53B":true,"0x7F01614cA5198Ec979B1aAd1DAF0DE7e0a215BDF":true,"0xdD67459D3e98EdDAA9770EbB7C38fF8F643f229f":true,"0x4729D9f61c0159F5e02D2C2e5937B3225e55442C":true,"0xF6e667bD3C914A336aFB57C38ABbF6ef41e2e7c8":true,"0x2e5D10A48C00cFcc6A31af873118d739323Ff71B":true,"0x9080f8A35Da53F4200a68533FB1dC1cA05357bDB":true,"0x88a5c6D94634Abd7745f5348e5D8C42868ed4AC3":true,"0xB36a4c6cDeDea3f31b3d16F33553F93b96b178F4":true,"0x58b09FD12863218F2ca156808C2Ae48aaCD0c072":true,"0xaF3A3B4685008ebDD1fF98fc47A14D3ab5ffCfc1":true} \ No newline at end of file diff --git a/scripts/multichain/bridgeInComposedMsg.ts b/scripts/multichain/bridgeInComposedMsg.ts index 7ccca39fe..5ae456cb5 100644 --- a/scripts/multichain/bridgeInComposedMsg.ts +++ b/scripts/multichain/bridgeInComposedMsg.ts @@ -47,17 +47,32 @@ async function prepareSend( composeMsg: string, stargatePoolAddress: string, decimals: number, + nativeTopUpAmount: BigNumber = BigNumber.from(0), // Amount of native tokens to top up user's multichain balance extraGas = 500000, slippageBps = 100 // Default 1% slippage tolerance ) { const GAS_LIMIT = 8000000; // 8M gas limit for the executor const LZ_RECEIVE_GAS_ESTIMATION = 8000000; // 8M gas units needed for lzCompose - // Calculate msgValue for lzReceive on destination chain - // e.g. 50,000 gas * 0.1 gwei (100,000,000 wei) = 5,000,000,000,000 wei + // Calculate msgValue for lzCompose on destination chain + // This includes: + // 1. Gas cost for executing lzCompose: LZ_RECEIVE_GAS_ESTIMATION * gasPrice + // 2. Native token top-up amount to credit to user's multichain balance: nativeTopUpAmount const destProvider = new ethers.providers.JsonRpcProvider("https://sepolia-rollup.arbitrum.io/rpc"); const gasPrice = await destProvider.getGasPrice(); - const msgValue = LZ_RECEIVE_GAS_ESTIMATION * gasPrice.toNumber(); - const extraOptions = Options.newOptions().addExecutorComposeOption(0, GAS_LIMIT, msgValue); + const gasValueForCompose = BigNumber.from(LZ_RECEIVE_GAS_ESTIMATION).mul(gasPrice); + const msgValue = gasValueForCompose.add(nativeTopUpAmount); + + console.log(`lzCompose msg.value breakdown:`); + console.log( + ` Gas cost (${LZ_RECEIVE_GAS_ESTIMATION} gas * ${ethers.utils.formatUnits( + gasPrice, + "gwei" + )} gwei): ${ethers.utils.formatEther(gasValueForCompose)} ETH` + ); + console.log(` Native top-up: ${ethers.utils.formatEther(nativeTopUpAmount)} ETH`); + console.log(` Total msg.value: ${ethers.utils.formatEther(msgValue)} ETH`); + + const extraOptions = Options.newOptions().addExecutorComposeOption(0, GAS_LIMIT, msgValue.toString()); const stargatePool: IStargate = await ethers.getContractAt("IStargate", stargatePoolAddress); console.log(`extraOptions: ${extraOptions.toHex()}`); @@ -111,6 +126,7 @@ async function getComposedMsg({ usdcAmount, gmAmount, glvAmount, + expectedNativeValue = 0, }: { account: string; actionType: ActionType; @@ -118,9 +134,16 @@ async function getComposedMsg({ usdcAmount: BigNumber; gmAmount: BigNumber; glvAmount: BigNumber; + expectedNativeValue?: number | string | BigNumber; }): Promise { if (actionType === ActionType.None) { - return ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, "0x"]); + // Encode message data: (ActionType, expectedNativeValue, actionData) + // ActionType.None = 0, no actionData = "0x" + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [0 /* ActionType.None */, expectedNativeValue, "0x"] + ); + return ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); } const srcChainId = await hre.ethers.provider.getNetwork().then((network) => network.chainId); @@ -203,7 +226,7 @@ async function getComposedMsg({ ethUsdMarket.marketToken ); - const message = await encodeDepositMessage(depositParams, account); + const message = await encodeDepositMessage(depositParams, account, expectedNativeValue); return message; } @@ -284,7 +307,7 @@ async function getComposedMsg({ throw new Error("Insufficient GM in user's multichain account"); } - const message = await encodeWithdrawalMessage(withdrawalParams, account); + const message = await encodeWithdrawalMessage(withdrawalParams, account, expectedNativeValue); return message; } @@ -364,7 +387,7 @@ async function getComposedMsg({ ETH_USD_GLV_ADDRESS ); - const message = await encodeGlvDepositMessage(createGlvDepositParams, account); + const message = await encodeGlvDepositMessage(createGlvDepositParams, account, expectedNativeValue); return message; } @@ -442,7 +465,7 @@ async function getComposedMsg({ ETH_USD_GLV_ADDRESS ); - const message = await encodeGlvWithdrawalMessage(createGlvWithdrawalParams, account); + const message = await encodeGlvWithdrawalMessage(createGlvWithdrawalParams, account, expectedNativeValue); return message; } @@ -470,7 +493,12 @@ async function getComposedMsg({ gelatoRelayFeeAmount: 0, }; - const message = await encodeSetTraderReferralCodeMessage(setTraderReferralCodeParams, referralCode, account); + const message = await encodeSetTraderReferralCodeMessage( + setTraderReferralCodeParams, + referralCode, + account, + expectedNativeValue + ); return message; } @@ -561,7 +589,7 @@ async function getComposedMsg({ ethUsdMarket.marketToken ); - const message = await encodeDepositMessage(depositParams, account); + const message = await encodeDepositMessage(depositParams, account, expectedNativeValue); return message; } @@ -642,7 +670,7 @@ async function getComposedMsg({ ethUsdMarket.marketToken ); - const message = await encodeWithdrawalMessage(withdrawalParams, account); + const message = await encodeWithdrawalMessage(withdrawalParams, account, expectedNativeValue); return message; } @@ -731,7 +759,7 @@ async function getComposedMsg({ ETH_USD_GLV_ADDRESS ); - const message = await encodeGlvDepositMessage(createGlvDepositParams, account); + const message = await encodeGlvDepositMessage(createGlvDepositParams, account, expectedNativeValue); return message; } @@ -822,14 +850,14 @@ async function getComposedMsg({ ETH_USD_GLV_ADDRESS ); - const message = await encodeGlvWithdrawalMessage(createGlvWithdrawalParams, account); + const message = await encodeGlvWithdrawalMessage(createGlvWithdrawalParams, account, expectedNativeValue); return message; } } } -// ACTION_TYPE= npx hardhat run --network sepolia scripts/multichain/bridgeInComposedMsg.ts +// ACTION_TYPE= NATIVE_TOPUP=0.01 npx hardhat run --network sepolia scripts/multichain/bridgeInComposedMsg.ts async function main() { if (!process.env.ACTION_TYPE) { throw new Error( @@ -840,6 +868,11 @@ async function main() { const [wallet] = await hre.ethers.getSigners(); const account = wallet.address; + // Parse native token top-up amount from environment variable (in ETH) + const nativeTopUpEth = process.env.NATIVE_TOPUP || "0"; + const nativeTopUpAmount = ethers.utils.parseEther(nativeTopUpEth); + console.log(`Native token top-up: ${nativeTopUpEth} ETH (${nativeTopUpAmount.toString()} wei)`); + // Bridge USDC (ETH bridging fails due to Stargate insufficient funds for path) const usdc: ERC20 = await ethers.getContractAt("ERC20", STARGATE_USDC_SEPOLIA); const usdcBalance = await usdc.balanceOf(account); @@ -864,6 +897,7 @@ async function main() { usdcAmount, gmAmount, glvAmount, + expectedNativeValue: nativeTopUpAmount, }); const { @@ -871,7 +905,7 @@ async function main() { sendParam, messagingFee, stargatePool: stargatePoolUsdc, - } = await prepareSend(usdcAmount, composedMsg, STARGATE_POOL_USDC_SEPOLIA, 6); + } = await prepareSend(usdcAmount, composedMsg, STARGATE_POOL_USDC_SEPOLIA, 6, nativeTopUpAmount); const { gasPrice, gasLimit } = await getIncreasedValues({ sendParam, diff --git a/scripts/multichain/bridgeInCrossChain.ts b/scripts/multichain/bridgeInCrossChain.ts index 26695b9e8..b4102cb6e 100644 --- a/scripts/multichain/bridgeInCrossChain.ts +++ b/scripts/multichain/bridgeInCrossChain.ts @@ -22,6 +22,9 @@ const { ethers } = hre; // IOFT is being used since it's more general, but IStargate has identical // interface, tho only difference being the additional `sendToken` method +// Fully qualified name to resolve ambiguity between multiple IOFT artifacts +const IOFT_FQN = "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol:IOFT"; + // Sepolia const STARGATE_POOL_USDC_SEPOLIA = "0x4985b8fcEA3659FD801a5b857dA1D00e985863F0"; const GM_OFT = "0xe4EBcAC4a2e6CBEE385eE407f7D5E278Bc07e11e"; @@ -36,8 +39,20 @@ const ETH_USD_GLV_ADDRESS = "0xAb3567e55c205c62B141967145F37b7695a9F854"; // GMX const layerZeroProviderJson = import("../../deployments/arbitrumSepolia/LayerZeroProvider.json"); -async function getComposedMsg({ account }: { account: string }): Promise { - return ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, "0x"]); +async function getComposedMsg({ + account, + expectedNativeValue = 0, +}: { + account: string; + expectedNativeValue?: number | string | BigNumber; +}): Promise { + // Encode message data: (ActionType, expectedNativeValue, actionData) + // ActionType.None = 0, no actionData = "0x" + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [0 /* ActionType.None */, expectedNativeValue, "0x"] + ); + return ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); } async function prepareSend( @@ -45,20 +60,35 @@ async function prepareSend( composeMsg: string, oftAddress: string, decimals: number, + nativeTopUpAmount: BigNumber = BigNumber.from(0), // Amount of native tokens to top up user's multichain balance gasLimit = 500000, extraGasForLzCompose = 500000, slippageBps = 100 // Default 1% slippage tolerance ) { - // Calculate msgValue for lzReceive on destination chain - // e.g. 50,000 gas * 0.1 gwei (100,000,000 wei) = 5,000,000,000,000 wei + // Calculate msgValue for lzCompose on destination chain + // This includes: + // 1. Gas cost for executing lzCompose: extraGasForLzCompose * gasPrice + // 2. Native token top-up amount to credit to user's multichain balance: nativeTopUpAmount const destProvider = new ethers.providers.JsonRpcProvider("https://sepolia-rollup.arbitrum.io/rpc"); const gasPrice = await destProvider.getGasPrice(); - const msgValue = extraGasForLzCompose * gasPrice.toNumber(); + const gasValueForCompose = BigNumber.from(extraGasForLzCompose).mul(gasPrice); + const msgValue = gasValueForCompose.add(nativeTopUpAmount); + + console.log(`lzCompose msg.value breakdown:`); + console.log( + ` Gas cost (${extraGasForLzCompose} gas * ${ethers.utils.formatUnits( + gasPrice, + "gwei" + )} gwei): ${ethers.utils.formatEther(gasValueForCompose)} ETH` + ); + console.log(` Native top-up: ${ethers.utils.formatEther(nativeTopUpAmount)} ETH`); + console.log(` Total msg.value: ${ethers.utils.formatEther(msgValue)} ETH`); + const extraOptions = Options.newOptions() .addExecutorLzReceiveOption(gasLimit, 0) - .addExecutorComposeOption(0, gasLimit, msgValue); + .addExecutorComposeOption(0, gasLimit, msgValue.toString()); - const oft: IOFT = await ethers.getContractAt("IOFT", oftAddress); + const oft: IOFT = await ethers.getContractAt(IOFT_FQN, oftAddress); console.log(`extraOptions: ${extraOptions.toHex()}`); // Calculate minAmountLD with slippage tolerance const amountBN = BigNumber.from(amount); @@ -92,17 +122,22 @@ async function prepareSend( }; } -// TOKEN=USDC npx hardhat run --network sepolia scripts/multichain/bridgeInCrossChain.ts +// TOKEN=USDC NATIVE_TOPUP=0.01 npx hardhat run --network sepolia scripts/multichain/bridgeInCrossChain.ts async function main() { const [wallet] = await hre.ethers.getSigners(); const account = wallet.address; + // Parse native token top-up amount from environment variable (in ETH) + const nativeTopUpEth = process.env.NATIVE_TOPUP || "0"; + const nativeTopUpAmount = ethers.utils.parseEther(nativeTopUpEth); + console.log(`Native token top-up: ${nativeTopUpEth} ETH (${nativeTopUpAmount.toString()} wei)`); + let amount: BigNumber; let valueToSend; let sendParam; let messagingFee; let oft; - const composedMsg = await getComposedMsg({ account }); + const composedMsg = await getComposedMsg({ account, expectedNativeValue: nativeTopUpAmount }); if (process.env.TOKEN === "ETH") { amount = expandDecimals(Number(process.env.AMOUNT) || 20, 16); // 0.2 ETH @@ -110,7 +145,8 @@ async function main() { amount, composedMsg, STARGATE_POOL_NATIVE_SEPOLIA, - 6 + 6, + nativeTopUpAmount )); const { wntAddress } = await getDeployments(); await logMultichainBalance(account, "WNT", wntAddress); @@ -120,16 +156,29 @@ async function main() { amount, composedMsg, STARGATE_POOL_USDC_SEPOLIA, - 6 + 6, + nativeTopUpAmount )); await logMultichainBalance(account, "USDC", STARGATE_POOL_USDC_SEPOLIA, 6); } else if (process.env.TOKEN === "GM") { amount = expandDecimals(Number(process.env.AMOUNT) || 3, 18); // 3 GM - ({ valueToSend, sendParam, messagingFee, oft } = await prepareSend(amount, composedMsg, GM_OFT, 18)); + ({ valueToSend, sendParam, messagingFee, oft } = await prepareSend( + amount, + composedMsg, + GM_OFT, + 18, + nativeTopUpAmount + )); await logMultichainBalance(account, "GM", ETH_USD_MARKET_TOKEN); } else if (process.env.TOKEN === "GLV") { amount = expandDecimals(Number(process.env.AMOUNT) || 1, 18); // 1 GLV - ({ valueToSend, sendParam, messagingFee, oft } = await prepareSend(amount, composedMsg, GLV_OFT, 18)); + ({ valueToSend, sendParam, messagingFee, oft } = await prepareSend( + amount, + composedMsg, + GLV_OFT, + 18, + nativeTopUpAmount + )); await logMultichainBalance(account, "GLV", ETH_USD_GLV_ADDRESS); } else { throw new Error("⚠️ Unsupported TOKEN type. Use 'USDC', 'GM', or 'GLV'."); diff --git a/scripts/roles/rolesToAdd/arbitrum.ts b/scripts/roles/rolesToAdd/arbitrum.ts index 9dbc72fa3..df278092c 100644 --- a/scripts/roles/rolesToAdd/arbitrum.ts +++ b/scripts/roles/rolesToAdd/arbitrum.ts @@ -1,6 +1,22 @@ export const ROLES_TO_ADD = [ { - role: "CONTROLLER", - member: "0xe68CAAACdf6439628DFD2fe624847602991A31eB", + role: "CONTRIBUTOR_DISTRIBUTOR", + member: "0xf09d66cf7debcdebf965f1ac6527e1aa5d47a745", + }, + { + role: "CONTRIBUTOR_DISTRIBUTOR", + member: "0x0765678b4f2b45fa9604264a63762e2fe460df64", + }, + { + role: "CONTRIBUTOR_DISTRIBUTOR", + member: "0xd5f8b9ba4255b2f73b06f245fcca73d114d1d460", + }, + { + role: "CONTRIBUTOR_DISTRIBUTOR", + member: "0xf86ef7f0bb90a05a932781c5cb6eefe55e486107", + }, + { + role: "CONTRIBUTOR_DISTRIBUTOR", + member: "0x9494410ec39ce9660acb4562963dd8841b3e926c", }, ]; diff --git a/scripts/syncContributorPayments.ts b/scripts/syncContributorPayments.ts new file mode 100644 index 000000000..e63623173 --- /dev/null +++ b/scripts/syncContributorPayments.ts @@ -0,0 +1,207 @@ +// scripts/sync.ts +import hre from "hardhat"; +import fs from "fs"; +import path from "path"; +import { parse as fastParse } from "@fast-csv/parse"; +import { signExternally } from "../utils/signer"; +import { bigNumberify } from "../utils/math"; +import * as keys from "../utils/keys"; + +type Row = Record; + +const TOKENS = ["GMX", "USDC"]; + +const sanitizeNumeric = (s?: string) => + String(s ?? "0") + .replace(/,/g, "") + .trim() || "0"; + +// fast-csv reader (streaming) +function readCsvFile(filePath: string): Promise { + return new Promise((resolve, reject) => { + const rows: Row[] = []; + fs.createReadStream(filePath) + .pipe( + fastParse({ + headers: true, + ignoreEmpty: true, + trim: true, + }) + ) + .on("error", reject) + .on("data", (row: Row) => rows.push(row)) + .on("end", () => resolve(rows)); + }); +} + +async function main() { + if (!TOKENS.length) throw new Error("TOKENS is empty."); + + const [signer] = await hre.ethers.getSigners(); + + // Contracts via hardhat-deploy + const contributorHandler = await hre.ethers.getContract("ContributorHandler", signer); + const dataStore = await hre.ethers.getContract("DataStore"); + const multicall = await hre.ethers.getContract("Multicall3"); // ← added + + // Token metadata via hre.gmx.getTokens() + const tokensMeta = await (hre as any).gmx.getTokens(); + const tokenAddressesBySymbol: Record = {}; + const tokenDecimalsBySymbol: Record = {}; + for (const symbol of TOKENS) { + const meta = tokensMeta[symbol]; + if (!meta?.address || meta.decimals == null) throw new Error(`Token ${symbol} missing in hre.gmx.getTokens()`); + tokenAddressesBySymbol[symbol] = meta.address; + tokenDecimalsBySymbol[symbol] = Number(meta.decimals); + } + + // Read all CSVs in data/payments + const csvDirectory = path.resolve("data/payments"); + const csvFiles = fs + .readdirSync(csvDirectory) + .filter((f) => f.toLowerCase().endsWith(".csv")) + .map((f) => path.join(csvDirectory, f)); + if (!csvFiles.length) throw new Error("No CSV files in data/payments/"); + + // Aggregate per account per token + const desiredAmountsByAccount: Record> = {}; + const csvAccountsSet = new Set(); + + for (const csvFilePath of csvFiles) { + const rows = await readCsvFile(csvFilePath); + for (const row of rows) { + const account = row.Address.trim().toLowerCase(); + if (!account) continue; + if (account === "-") continue; + if (!ethers.utils.isAddress(account)) { + throw new Error(`Invalid address: ${account}`); + } + + csvAccountsSet.add(account); + desiredAmountsByAccount[account] ||= {}; + + for (const symbol of TOKENS) { + const cell = row[symbol]; + if (!cell) continue; + const decimals = tokenDecimalsBySymbol[symbol]; + const parsedAmount = hre.ethers.utils.parseUnits(sanitizeNumeric(cell), decimals); + console.log(`${account}: ${parsedAmount.toString()} ${symbol}`); + desiredAmountsByAccount[account][symbol] = (desiredAmountsByAccount[account][symbol] ?? bigNumberify(0)).add( + parsedAmount + ); + } + } + } + + // On-chain account list (diff using keys.CONTRIBUTOR_ACCOUNT_LIST) + const onchainAddressList: string[] = await dataStore.getAddressValuesAt(keys.CONTRIBUTOR_ACCOUNT_LIST, 0, 1000); + const onchainAccountSet = new Set(onchainAddressList.map((a) => a.toLowerCase())); + + // ------------------------------------------------------------ + // NEW: bulk read current values via Multicall3 and DataStore.getUint + // ------------------------------------------------------------ + type Pair = { account: string; tokenAddr: string; desired: any }; + const accountTokenPairs: Pair[] = []; + for (const [account, tokenMap] of Object.entries(desiredAmountsByAccount)) { + for (const symbol of TOKENS) { + const desired = tokenMap[symbol] ?? bigNumberify(0); + accountTokenPairs.push({ account, tokenAddr: tokenAddressesBySymbol[symbol], desired }); + } + } + + const dataStoreInterface = dataStore.interface; + const readCalls = accountTokenPairs.map((p) => ({ + target: dataStore.address, + callData: dataStoreInterface.encodeFunctionData("getUint", [ + keys.contributorTokenAmountKey(p.account, p.tokenAddr), + ]), + })); + + const currentValuesByAccountToken: Record> = {}; + if (readCalls.length) { + const result = await multicall.callStatic.aggregate3(readCalls); + for (let i = 0; i < result.length; i++) { + const p = accountTokenPairs[i]; + const [val] = dataStoreInterface.decodeFunctionResult("getUint", result[i].returnData) as [any]; + (currentValuesByAccountToken[p.account] ||= {})[p.tokenAddr] = val; + } + } + // ------------------------------------------------------------ + + // Build calls + const encodedFunctionCalls: string[] = []; + + // add/remove accounts + for (const account of csvAccountsSet) { + if (!onchainAccountSet.has(account)) { + console.log(`add ${account}`); + encodedFunctionCalls.push(contributorHandler.interface.encodeFunctionData("addContributorAccount", [account])); + } + } + for (const account of onchainAccountSet) { + if (!csvAccountsSet.has(account)) { + console.log(`remove ${account}`); + encodedFunctionCalls.push(contributorHandler.interface.encodeFunctionData("removeContributorAccount", [account])); + } + } + + // setContributorAmount per account — ONLY IF NEEDED (diff vs on-chain) + const totalsBySymbol: Record = {}; + for (const [account, tokenMap] of Object.entries(desiredAmountsByAccount)) { + const tokenAddressesToSet: string[] = []; + const amountsToSet: any[] = []; + for (const symbol of TOKENS) { + const desired = tokenMap[symbol] ?? bigNumberify(0); + const tokenAddr = tokenAddressesBySymbol[symbol]; + const current = currentValuesByAccountToken[account]?.[tokenAddr] ?? bigNumberify(0); + totalsBySymbol[symbol] = (totalsBySymbol[symbol] ?? bigNumberify(0)).add(desired); + if (!current.eq(desired)) { + tokenAddressesToSet.push(tokenAddr); + amountsToSet.push(desired); + } + } + if (tokenAddressesToSet.length) { + for (let i = 0; i < tokenAddressesToSet.length; i++) { + console.log("set", account, tokenAddressesToSet[i], amountsToSet[i].toString()); + } + + encodedFunctionCalls.push( + contributorHandler.interface.encodeFunctionData("setContributorAmount", [ + account, + tokenAddressesToSet, + amountsToSet, + ]) + ); + } + } + + // Totals (with commas / without) + const formatAmountWithCommas = (x: any, decimals: number) => { + const s = hre.ethers.utils.formatUnits(x, decimals); + return `${Number(s).toLocaleString("en-US")}`; + }; + + console.log("CSV files:", csvFiles.length); + console.log("Unique CSV accounts:", csvAccountsSet.size); + for (const symbol of TOKENS) { + console.log( + `${symbol} total: ${formatAmountWithCommas( + totalsBySymbol[symbol] ?? bigNumberify(0), + tokenDecimalsBySymbol[symbol] + )}` + ); + } + console.log("Encoded calls:", encodedFunctionCalls.length); + + const shouldWrite = process.env.WRITE === "true"; + if (shouldWrite) { + await signExternally(await contributorHandler.populateTransaction.multicall(encodedFunctionCalls)); + } else { + console.log("NOTE: executed in read-only mode, no transactions were sent"); + } +} + +main().catch((ex) => { + console.error(ex); + process.exit(1); +}); diff --git a/scripts/syncVirtualPriceImpact.ts b/scripts/syncVirtualPriceImpact.ts new file mode 100644 index 000000000..a5c9196d7 --- /dev/null +++ b/scripts/syncVirtualPriceImpact.ts @@ -0,0 +1,159 @@ +import hre from "hardhat"; + +import { getMarketKey, getMarketTokenAddresses, getOnchainMarkets } from "../utils/market"; +import { encodeData } from "../utils/hash"; +import * as keys from "../utils/keys"; +import { getFullKey } from "../utils/config"; +import { bigNumberify } from "../utils/math"; + +const write = process.env.WRITE === "true"; + +// NOTE: it should be ensured that the market virtualTokenIdForIndexToken +// matches the on-chain value, before running this script + +async function processMarketGroup({ + virtualTokenIdForIndexToken, + markets, + tokens, + onchainMarketsByTokens, + multicall, + dataStore, + config, +}) { + console.log( + `checking ${markets.length} markets for ${virtualTokenIdForIndexToken}, ${ + virtualTokenIdForIndexToken === undefined + }` + ); + + const multicallReadParams = []; + + for (const marketConfig of markets) { + const [indexToken, longToken, shortToken] = getMarketTokenAddresses(marketConfig, tokens); + console.log( + ` indexToken: ${marketConfig.tokens.indexToken}, longToken: ${marketConfig.tokens.longToken}, shortToken: ${marketConfig.tokens.shortToken}` + ); + const marketKey = getMarketKey(indexToken, longToken, shortToken); + const onchainMarket = onchainMarketsByTokens[marketKey]; + + multicallReadParams.push({ + target: dataStore.address, + allowFailure: false, + callData: dataStore.interface.encodeFunctionData("getUint", [ + getFullKey( + keys.OPEN_INTEREST_IN_TOKENS, + encodeData(["address", "address", "bool"], [onchainMarket.marketToken, onchainMarket.longToken, true]) + ), + ]), + }); + + multicallReadParams.push({ + target: dataStore.address, + allowFailure: false, + callData: dataStore.interface.encodeFunctionData("getUint", [ + getFullKey( + keys.OPEN_INTEREST_IN_TOKENS, + encodeData(["address", "address", "bool"], [onchainMarket.marketToken, onchainMarket.shortToken, true]) + ), + ]), + }); + + multicallReadParams.push({ + target: dataStore.address, + allowFailure: false, + callData: dataStore.interface.encodeFunctionData("getUint", [ + getFullKey( + keys.OPEN_INTEREST_IN_TOKENS, + encodeData(["address", "address", "bool"], [onchainMarket.marketToken, onchainMarket.longToken, false]) + ), + ]), + }); + + multicallReadParams.push({ + target: dataStore.address, + allowFailure: false, + callData: dataStore.interface.encodeFunctionData("getUint", [ + getFullKey( + keys.OPEN_INTEREST_IN_TOKENS, + encodeData(["address", "address", "bool"], [onchainMarket.marketToken, onchainMarket.shortToken, true]) + ), + ]), + }); + } + + const result = await multicall.callStatic.aggregate3(multicallReadParams); + let totalLongOpenInterestInTokens = bigNumberify(0); + let totalShortOpenInterestInTokens = bigNumberify(0); + + for (let i = 0; i < result.length; i++) { + const value = bigNumberify(result[i].returnData); + + if (i % 4 < 2) { + totalLongOpenInterestInTokens = totalLongOpenInterestInTokens.add(value); + } else { + totalShortOpenInterestInTokens = totalShortOpenInterestInTokens.add(value); + } + } + + const virtualInventoryInTokens = totalShortOpenInterestInTokens.sub(totalLongOpenInterestInTokens); + + console.log(` totalLongOpenInterestInTokens: ${totalLongOpenInterestInTokens.toString()}`); + console.log(` totalShortOpenInterestInTokens: ${totalShortOpenInterestInTokens.toString()}`); + console.log(` virtualInventoryInTokens: ${virtualInventoryInTokens.toString()}`); + + if (write) { + const tx = await config.setInt( + keys.VIRTUAL_INVENTORY_FOR_POSITIONS_IN_TOKENS, + virtualTokenIdForIndexToken, + virtualInventoryInTokens + ); + + console.log("transaction sent", tx.hash); + await tx.wait(); + console.log("receipt received"); + } +} + +async function main() { + const dataStore = await hre.ethers.getContract("DataStore"); + const config = await hre.ethers.getContract("Config"); + const multicall = await hre.ethers.getContract("Multicall3"); + const { read } = hre.deployments; + + const markets = await hre.gmx.getMarkets(); + const onchainMarketsByTokens = await getOnchainMarkets(read, dataStore.address); + const tokens = await (hre as any).gmx.getTokens(); + + const marketsByVirtualTokenId = Object.values(markets).reduce((acc, market) => { + const key = market.virtualTokenIdForIndexToken; + if (key === undefined) return acc; + if (!acc[key]) acc[key] = []; + acc[key].push(market); + return acc; + }, {}); + + for (const [virtualTokenIdForIndexToken, markets] of Object.entries(marketsByVirtualTokenId)) { + await processMarketGroup({ + virtualTokenIdForIndexToken, + markets, + onchainMarketsByTokens, + tokens, + multicall, + dataStore, + config, + }); + } + + if (!write) { + console.warn("Script ran in read-only mode, no txns were sent"); + } +} + +main() + .then(() => { + process.exit(0); + }) + .catch((ex) => { + console.error(ex); + process.exit(1); + }); diff --git a/scripts/updateMarketConfigUtils.ts b/scripts/updateMarketConfigUtils.ts index 2a0c18340..a4416f970 100644 --- a/scripts/updateMarketConfigUtils.ts +++ b/scripts/updateMarketConfigUtils.ts @@ -162,6 +162,38 @@ const processMarkets = async ({ `maxShortTokenPoolUsdForDeposit ${marketLabel} (${marketToken}), ${shortToken}` ); + addConfigItem( + "uint", + keys.MAX_COLLATERAL_SUM, + encodeData(["address", "address", "bool"], [marketToken, longToken, true]), + marketConfig.maxLongCollateralSum.div(2), + `maxLongCollateralSum ${marketLabel} (${marketToken}), ${longToken}, true` + ); + + addConfigItem( + "uint", + keys.MAX_COLLATERAL_SUM, + encodeData(["address", "address", "bool"], [marketToken, longToken, false]), + marketConfig.maxLongCollateralSum.div(2), + `maxLongCollateralSum ${marketLabel} (${marketToken}), ${longToken}, false` + ); + + addConfigItem( + "uint", + keys.MAX_COLLATERAL_SUM, + encodeData(["address", "address", "bool"], [marketToken, shortToken, true]), + marketConfig.maxShortCollateralSum.div(2), + `maxShortCollateralSum ${marketLabel} (${marketToken}), ${shortToken}, true` + ); + + addConfigItem( + "uint", + keys.MAX_COLLATERAL_SUM, + encodeData(["address", "address", "bool"], [marketToken, shortToken, false]), + marketConfig.maxShortCollateralSum.div(2), + `maxShortCollateralSum ${marketLabel} (${marketToken}), ${shortToken}, false` + ); + addConfigItem( "uint", keys.SWAP_IMPACT_EXPONENT_FACTOR, diff --git a/scripts/updateRoles.ts b/scripts/updateRoles.ts index 154176b63..95b77448f 100644 --- a/scripts/updateRoles.ts +++ b/scripts/updateRoles.ts @@ -128,7 +128,7 @@ async function main() { if (!contractInfo.isCodeValidated) { console.log(`❌${contractInfo.name} is not valid. Sources do not match. See diff in validation folder`); } else { - console.log(`✅${contractInfo.name} is valid`); + console.log(`✅${contractInfo.name}, ${contractInfo.address} is valid`); } } diff --git a/scripts/validateMarketConfigsUtils.ts b/scripts/validateMarketConfigsUtils.ts index 812b40d55..84dd7cd6e 100644 --- a/scripts/validateMarketConfigsUtils.ts +++ b/scripts/validateMarketConfigsUtils.ts @@ -660,6 +660,18 @@ const recommendedMarketConfig = { expectedSwapImpactRatio: 20_000, expectedPositionImpactRatio: 12_000, }, + "XAUt0:XAUt0:XAUt0": { + negativePositionImpactFactor: exponentToFloat("9.29e-9"), + negativeSwapImpactFactor: 0, + expectedSwapImpactRatio: 10_000, + expectedPositionImpactRatio: 12_002, + }, + XAUt0: { + negativePositionImpactFactor: exponentToFloat("9.29e-9"), + negativeSwapImpactFactor: exponentToFloat("3.5e-9"), + expectedSwapImpactRatio: 20_000, + expectedPositionImpactRatio: 12_002, + }, }, arbitrumSepolia: { BTC: { @@ -748,6 +760,10 @@ async function validatePerpConfig({ }); } + if (marketConfig.minCollateralFactor.lt(marketConfig.minCollateralFactorForLiquidation)) { + throw new Error(`minCollateralFactor < minCollateralFactorForLiquidation for ${marketLabel}`); + } + console.log("validatePerpConfig", indexTokenSymbol); const recommendedPerpConfig = recommendedMarketConfig[hre.network.name][`${indexTokenSymbol}:${longTokenSymbol}:${shortTokenSymbol}`] ?? diff --git a/test/config/Timelock.ts b/test/config/Timelock.ts index fbb6be337..3ad482c45 100644 --- a/test/config/Timelock.ts +++ b/test/config/Timelock.ts @@ -295,40 +295,6 @@ describe("Timelock", () => { expect(await roleStore.hasRole(user3.address, orderKeeperRole)).eq(false); }); - it("setOracleProviderForToken", async () => { - const salt = getRandomSalt(); - await expect( - timelockConfig - .connect(user2) - .signalSetOracleProviderForToken(oracle.address, wnt.address, user3.address, constants.HashZero, salt) - ) - .to.be.revertedWithCustomError(errorsContract, "Unauthorized") - .withArgs(user2.address, "TIMELOCK_ADMIN"); - - await timelockConfig - .connect(timelockAdmin) - .signalSetOracleProviderForToken(oracle.address, wnt.address, user3.address, constants.HashZero, salt); - - const { target, payload } = await setOracleProviderForTokenPayload(oracle.address, wnt.address, user3.address); - await expect(timelockConfig.connect(user2).execute(target, payload, constants.HashZero, salt)) - .to.be.revertedWithCustomError(errorsContract, "Unauthorized") - .withArgs(user2.address, "TIMELOCK_ADMIN"); - - await expect( - timelockConfig.connect(timelockAdmin).execute(target, payload, constants.HashZero, salt) - ).to.be.revertedWith("TimelockController: operation is not ready"); - - await time.increase(1 * 24 * 60 * 60 + 10); - - expect(await dataStore.getAddress(keys.oracleProviderForTokenKey(oracle.address, wnt.address))).eq( - fixture.contracts.gmOracleProvider.address - ); - - await timelockConfig.connect(timelockAdmin).execute(target, payload, constants.HashZero, salt); - - expect(await dataStore.getAddress(keys.oracleProviderForTokenKey(oracle.address, wnt.address))).eq(user3.address); - }); - it("setOracleProviderEnabled", async () => { const salt = getRandomSalt(); expect(await dataStore.getBool(keys.isOracleProviderEnabledKey(user3.address))).eq(false); diff --git a/test/exchange/BorrowingFees.ts b/test/exchange/BorrowingFees.ts index d0af8281c..fb29b5c64 100644 --- a/test/exchange/BorrowingFees.ts +++ b/test/exchange/BorrowingFees.ts @@ -39,7 +39,11 @@ describe("Exchange.BorrowingFees", () => { }); }); - it("borrowing fees", async () => { + async function testBorrowingFees(skipBorrowingFeeForSmallerSide) { + if (skipBorrowingFeeForSmallerSide) { + await dataStore.setBool(keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE, true); + } + await dataStore.setUint(keys.borrowingFactorKey(ethUsdMarket.marketToken, true), decimalToFloat(1, 7)); await dataStore.setUint(keys.borrowingFactorKey(ethUsdMarket.marketToken, false), decimalToFloat(2, 7)); await dataStore.setUint(keys.borrowingExponentFactorKey(ethUsdMarket.marketToken, true), decimalToFloat(1)); @@ -138,7 +142,7 @@ describe("Exchange.BorrowingFees", () => { ); // $967.684 expect(position1.fees.borrowing.borrowingFeeUsd).closeTo( - "5443200000000000000000000000000000", + skipBorrowingFeeForSmallerSide ? "0" : "5443200000000000000000000000000000", decimalToFloat(10, 3) ); // $5443.2 @@ -171,7 +175,7 @@ describe("Exchange.BorrowingFees", () => { decimalToFloat(10, 8) ); expect(await dataStore.getUint(keys.cumulativeBorrowingFactorKey(ethUsdMarket.marketToken, false))).eq( - "36288120000000000000000000000" + skipBorrowingFeeForSmallerSide ? "0" : "36288120000000000000000000000" ); // user1 increase short position by $1000 @@ -198,18 +202,23 @@ describe("Exchange.BorrowingFees", () => { ); // 0.004838432 expect(await dataStore.getUint(keys.cumulativeBorrowingFactorKey(ethUsdMarket.marketToken, false))).closeTo( - "36288240000000000000000000000", + skipBorrowingFeeForSmallerSide ? "0" : "36288240000000000000000000000", decimalToFloat(10, 8) ); // 0.03628824 await usingResult( getMarketTokenPriceWithPoolValue(fixture, { prices: prices.ethUsdMarket }), ([marketTokenPrice, poolValueInfo]) => { - expect(marketTokenPrice).closeTo("1001068487605242432177935697848", "10000000000000000000000"); // 1.00106848761 + expect(marketTokenPrice).closeTo( + skipBorrowingFeeForSmallerSide ? "1000161281605242432177935697848" : "1001068487605242432177935697848", + "10000000000000000000000" + ); // 1.00016128161 / 1.00106848761 expect(poolValueInfo.poolValue).closeTo( - "6006410925631454593067614187093608000", + skipBorrowingFeeForSmallerSide + ? "6000967689631454593067614187093608000" + : "6006410925631454593067614187093608000", "100000000000000000000000000000" - ); // 6006410.92563 + ); // 6,000,967.68963 // 6,006,410.92563 } ); @@ -250,13 +259,26 @@ describe("Exchange.BorrowingFees", () => { await usingResult( getMarketTokenPriceWithPoolValue(fixture, { prices: prices.ethUsdMarket }), ([marketTokenPrice, poolValueInfo]) => { - expect(marketTokenPrice).closeTo("1001068492544674256310833333333", "10000000000000000000000"); // 1.00106849254 + expect(marketTokenPrice).closeTo( + skipBorrowingFeeForSmallerSide ? "1000161284289174256310833333333" : "1001068492544674256310833333333", + "10000000000000000000000" + ); // 1.00106849254 expect(poolValueInfo.poolValue).closeTo( - "6006410955268045537865000000000000000", + skipBorrowingFeeForSmallerSide + ? "6000967705735045537865000000000000000" + : "6006410955268045537865000000000000000", "100000000000000000000000000000" ); // 6006410.95527 } ); + } + + it("borrowing fees", async () => { + await testBorrowingFees(false); + }); + + it("borrowing fees, SKIP_BORROWING_FEE_FOR_SMALLER_SIDE as true", async () => { + await testBorrowingFees(true); }); it("borrowing fees vary with time", async () => { diff --git a/test/exchange/FundingFees/AdaptiveFunding.ts b/test/exchange/FundingFees/AdaptiveFunding.ts index 167562f66..5cdb0a526 100644 --- a/test/exchange/FundingFees/AdaptiveFunding.ts +++ b/test/exchange/FundingFees/AdaptiveFunding.ts @@ -3,9 +3,11 @@ import { time } from "@nomicfoundation/hardhat-network-helpers"; import { usingResult } from "../../../utils/use"; import { deployFixture } from "../../../utils/fixture"; +import { getExecuteParams } from "../../../utils/exchange"; import { expandDecimals, decimalToFloat } from "../../../utils/math"; import { handleDeposit } from "../../../utils/deposit"; import { OrderType, handleOrder } from "../../../utils/order"; +import { getEventData } from "../../../utils/event"; import { prices } from "../../../utils/prices"; import * as keys from "../../../utils/keys"; @@ -36,7 +38,11 @@ describe("Exchange.FundingFees.AdaptiveFunding", () => { }); }); - it("adaptive funding", async () => { + async function testAdaptiveFunding(useOpenInterestInTokensForBalance) { + if (useOpenInterestInTokensForBalance) { + await dataStore.setBool(keys.USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE, true); + } + await dataStore.setUint(keys.fundingFactorKey(ethUsdMarket.marketToken), decimalToFloat(1, 10)); await dataStore.setUint(keys.fundingExponentFactorKey(ethUsdMarket.marketToken), decimalToFloat(1)); @@ -361,5 +367,132 @@ describe("Exchange.FundingFees.AdaptiveFunding", () => { ); // -0.00475% } ); + + // increase position at a different wnt price to create some difference between openInterestInTokens and openInterestInUsd + // the open interest in USD should be balanced after this order, the open interest in tokens should not be balanced + await handleOrder(fixture, { + create: { + account: user0, + market: ethUsdMarket, + initialCollateralToken: wnt, + sizeDeltaUsd: decimalToFloat(12_001), + acceptablePrice: expandDecimals(5050, 12), + orderType: OrderType.MarketIncrease, + isLong: true, + }, + execute: { ...getExecuteParams(fixture, { prices: [prices.usdc, prices.wnt.increased] }) }, + }); + + expect(await dataStore.getUint(keys.openInterestKey(ethUsdMarket.marketToken, wnt.address, true))).eq( + "106001000000000000000000000000000000" + ); // 106,001 + expect(await dataStore.getUint(keys.openInterestKey(ethUsdMarket.marketToken, usdc.address, false))).eq( + "106001000000000000000000000000000000" + ); // 106,001 + + expect(await dataStore.getUint(keys.openInterestInTokensKey(ethUsdMarket.marketToken, wnt.address, true))).eq( + "21190637450199203187" + ); // 21.190637450199203187 + expect(await dataStore.getUint(keys.openInterestInTokensKey(ethUsdMarket.marketToken, usdc.address, false))).eq( + "21200200000000000000" + ); // 21.2002 + + await time.increase(10 * 60); + + if (useOpenInterestInTokensForBalance) { + await usingResult( + reader.getMarketInfo(dataStore.address, prices.ethUsdMarket, ethUsdMarket.marketToken), + (marketInfo) => { + expect(marketInfo.nextFunding.longsPayShorts).eq(false); + expect(marketInfo.nextFunding.fundingFactorPerSecond).closeTo( + "35773029394356302617778206", + "100000000000000000000000" + ); // 0.00357% + expect(marketInfo.nextFunding.nextSavedFundingFactorPerSecond).closeTo( + "-35773029394356302617778206", + "100000000000000000000000" + ); // -0.00357% + } + ); + } else { + // if !useOpenInterestInTokensForBalance there should only be a minor change in funding + await usingResult( + reader.getMarketInfo(dataStore.address, prices.ethUsdMarket, ethUsdMarket.marketToken), + (marketInfo) => { + expect(marketInfo.nextFunding.longsPayShorts).eq(false); + expect(marketInfo.nextFunding.fundingFactorPerSecond).closeTo( + "47773029394356302617778206", + "100000000000000000000000" + ); // 0.00475% + expect(marketInfo.nextFunding.nextSavedFundingFactorPerSecond).closeTo( + "-47773029394356302617778206", + "100000000000000000000000" + ); // -0.00475% + } + ); + } + + await dataStore.setUint(keys.positionImpactFactorKey(ethUsdMarket.marketToken, true), decimalToFloat(5, 9)); + await dataStore.setUint(keys.positionImpactFactorKey(ethUsdMarket.marketToken, false), decimalToFloat(1, 8)); + await dataStore.setUint(keys.positionImpactExponentFactorKey(ethUsdMarket.marketToken), decimalToFloat(2, 0)); + + // is useOpenInterestInTokensForBalance, there should be a small positive price impact + // since the openInterestInTokens for longs is slightly smaller than for shorts + await handleOrder(fixture, { + create: { + account: user0, + market: ethUsdMarket, + initialCollateralDeltaAmount: expandDecimals(10, 18), + initialCollateralToken: wnt, + sizeDeltaUsd: decimalToFloat(30), + acceptablePrice: expandDecimals(5050, 12), + orderType: OrderType.MarketIncrease, + isLong: true, + }, + execute: { + gasUsageLabel: "executeOrder", + afterExecution: ({ logs }) => { + const positionIncreaseEvent = getEventData(logs, "PositionIncrease"); + // 0.00000984141 / -0.000009 + expect(positionIncreaseEvent.pendingPriceImpactUsd).eq( + useOpenInterestInTokensForBalance ? "9843824701195219287825000" : "-8999999999999999859640000" + ); + }, + }, + }); + + // the position should be fully closeable + await handleOrder(fixture, { + create: { + account: user0, + market: ethUsdMarket, + initialCollateralToken: wnt, + sizeDeltaUsd: decimalToFloat(106_031), + acceptablePrice: expandDecimals(4050, 12), + orderType: OrderType.MarketDecrease, + isLong: true, + }, + execute: { + ...getExecuteParams(fixture, { prices: [prices.usdc, prices.wnt.decreased] }), + gasUsageLabel: "executeOrder", + afterExecution: ({ logs }) => { + const positionDecreaseEvent = getEventData(logs, "PositionDecrease"); + expect(positionDecreaseEvent.sizeInUsd).eq("0"); + expect(positionDecreaseEvent.priceImpactUsd).eq( + useOpenInterestInTokensForBalance + ? "-111465017696232642237559789270000" // -111.465017696 + : "-112362115509999998076470009600000" // -112.36211551 + ); + }, + }, + }); + } + + it("adaptive funding", async () => { + await testAdaptiveFunding(false); + }); + + it("adaptive funding with USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE as true", async () => { + await testAdaptiveFunding(true); }); }); diff --git a/test/exchange/FundingFees/SingleTokenMarket.ts b/test/exchange/FundingFees/SingleTokenMarket.ts index 93ec598fc..7347d4154 100644 --- a/test/exchange/FundingFees/SingleTokenMarket.ts +++ b/test/exchange/FundingFees/SingleTokenMarket.ts @@ -37,7 +37,11 @@ describe("Exchange.FundingFees.SingleTokenMarket", () => { }); }); - it("funding fees, single token market", async () => { + async function testFunding(useOpenInterestInTokensForBalance) { + if (useOpenInterestInTokensForBalance) { + await dataStore.setBool(keys.USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE, true); + } + await dataStore.setUint(keys.fundingFactorKey(ethUsdSingleTokenMarket.marketToken), decimalToFloat(1, 10)); await dataStore.setUint(keys.fundingExponentFactorKey(ethUsdSingleTokenMarket.marketToken), decimalToFloat(1)); @@ -186,5 +190,13 @@ describe("Exchange.FundingFees.SingleTokenMarket", () => { keys.claimableFundingAmountKey(ethUsdSingleTokenMarket.marketToken, usdc.address, user1.address) ) ).eq("8064018"); // 8.064018 USD + } + + it("funding fees, single token market", async () => { + await testFunding(false); + }); + + it("funding fees, single token market, USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE as true", async () => { + await testFunding(true); }); }); diff --git a/test/multichain/LayerZeroProvider.ts b/test/multichain/LayerZeroProvider.ts index 5e9ad9b35..5bbe00528 100644 --- a/test/multichain/LayerZeroProvider.ts +++ b/test/multichain/LayerZeroProvider.ts @@ -474,6 +474,138 @@ describe("LayerZeroProvider", () => { }); }); + describe("Native Token Top-Up via msg.value", () => { + beforeEach(async () => { + await dataStore.setUint(keys.eidToSrcChainId(await mockStargatePoolUsdc.SRC_EID()), chainId); + }); + + it("should credit msg.value to user's multichain balance when bridging USDC", async () => { + const usdcAmount = expandDecimals(1000, 6); + const nativeTopUp = expandDecimals(1, 17); // 0.1 ETH + + const wntBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user0.address, wnt.address)); + const usdcBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user0.address, usdc.address)); + + await bridgeInTokens(fixture, { + account: user0, + token: usdc, + amount: usdcAmount, + nativeTopUpAmount: nativeTopUp, + }); + + // Verify USDC was credited + expect(await dataStore.getUint(keys.multichainBalanceKey(user0.address, usdc.address))).eq( + usdcBalanceBefore.add(usdcAmount) + ); + + // Verify native token was credited (wrapped to WNT) + expect(await dataStore.getUint(keys.multichainBalanceKey(user0.address, wnt.address))).eq( + wntBalanceBefore.add(nativeTopUp) + ); + }); + + it("should credit msg.value when bridging native ETH", async () => { + const ethBridgeAmount = expandDecimals(1, 18); // 1 ETH for bridging + const nativeTopUp = expandDecimals(5, 17); // 0.5 ETH for top-up + const totalMsgValue = ethBridgeAmount.add(nativeTopUp); + + const wntBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address)); + + await bridgeInTokens(fixture, { + account: user1, + token: undefined, // undefined means sending native tokens (ETH) + amount: ethBridgeAmount, + nativeTopUpAmount: nativeTopUp, + }); + + // Should credit both: bridged ETH + top-up ETH + expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).eq( + wntBalanceBefore.add(totalMsgValue) + ); + }); + + it("should work with msg.value = 0", async () => { + const usdcAmount = expandDecimals(1000, 6); + + const usdcBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user0.address, usdc.address)); + const wntBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user0.address, wnt.address)); + + // No native top-up (nativeTopUpAmount not specified) + await bridgeInTokens(fixture, { + account: user0, + token: usdc, + amount: usdcAmount, + }); + + // Should succeed with msg.value = 0 + expect(await dataStore.getUint(keys.multichainBalanceKey(user0.address, usdc.address))).eq( + usdcBalanceBefore.add(usdcAmount) + ); + + // WNT balance should not change + expect(await dataStore.getUint(keys.multichainBalanceKey(user0.address, wnt.address))).eq(wntBalanceBefore); + }); + + it("should revert if msg.value is less than expectedNativeValue", async () => { + const usdcAmount = expandDecimals(1000, 6); + const expectedNativeValue = expandDecimals(2, 17); // 0.2 ETH expected + const actualSent = expandDecimals(1, 17); // 0.1 ETH actually sent (insufficient) + + await usdc.mint(user0.address, usdcAmount); + await usdc.connect(user0).approve(mockStargatePoolUsdc.address, usdcAmount); + + // Encode message without action but with expectedNativeValue + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [0, expectedNativeValue, "0x"] // ActionType.None, expectedNativeValue, no actionData + ); + + const encodedMessage = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [user0.address, data]); + + // Should revert because actualSent (0.1 ETH) < expectedNativeValue (0.2 ETH) + await expect( + mockStargatePoolUsdc + .connect(user0) + .sendToken(layerZeroProvider.address, usdcAmount, encodedMessage, { value: actualSent }) + ).to.be.revertedWithCustomError(layerZeroProvider, "InsufficientNativeTokenAmount"); + }); + + it("should succeed when msg.value >= expectedNativeValue and credit full amount", async () => { + const usdcAmount = expandDecimals(1000, 6); + const expectedNativeValue = expandDecimals(5, 16); // 0.05 ETH expected + const actualSent = expandDecimals(2, 17); // 0.2 ETH sent (more than expected) + + await usdc.mint(user0.address, usdcAmount); + await usdc.connect(user0).approve(mockStargatePoolUsdc.address, usdcAmount); + + // Encode message without action but with expectedNativeValue + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [0, expectedNativeValue, "0x"] // ActionType.None, expectedNativeValue, no actionData + ); + + const encodedMessage = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [user0.address, data]); + + const wntBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user0.address, wnt.address)); + const usdcBalanceBefore = await dataStore.getUint(keys.multichainBalanceKey(user0.address, usdc.address)); + + // Should succeed because actualSent (0.2 ETH) >= expectedNativeValue (0.05 ETH) + await mockStargatePoolUsdc + .connect(user0) + .sendToken(layerZeroProvider.address, usdcAmount, encodedMessage, { value: actualSent }); + + // USDC should be credited normally + expect(await dataStore.getUint(keys.multichainBalanceKey(user0.address, usdc.address))).eq( + usdcBalanceBefore.add(usdcAmount) + ); + + // User gets the full actualSent amount (0.2 ETH), not just expectedNativeValue + expect(await dataStore.getUint(keys.multichainBalanceKey(user0.address, wnt.address))).eq( + wntBalanceBefore.add(actualSent) + ); + }); + }); + describe("actionType: SetTraderReferralCode", () => { const referralCode = hashString("referralCode"); diff --git a/test/multichain/MultichainGmRouter.ts b/test/multichain/MultichainGmRouter.ts index 784cee2b4..73d285656 100644 --- a/test/multichain/MultichainGmRouter.ts +++ b/test/multichain/MultichainGmRouter.ts @@ -20,6 +20,7 @@ import { executeShift, getShiftCount, getShiftKeys } from "../../utils/shift"; import { encodeBridgeOutDataList, bridgeInTokens } from "../../utils/multichain"; import { getRelayParams } from "../../utils/relay/helpers"; import { errorsContract } from "../../utils/error"; +import { GAS_BUFFER } from "../../utils/gas"; describe("MultichainGmRouter", () => { let fixture; @@ -199,11 +200,11 @@ describe("MultichainGmRouter", () => { expect(await getDepositCount(dataStore)).eq(0); expect(await wnt.balanceOf(multichainVault.address)).to.approximately( expandDecimals(2095, 12), // feeAmount - keeperFee = 0.004 - ~0.0019 = ~0.0021 (e.g. 0.002095) - expandDecimals(1, 12) + GAS_BUFFER.DEPOSIT ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).to.approximately( expandDecimals(2095, 12), // feeAmount - keeperFee = 0.004 - ~0.0019 = ~0.0021 (e.g. 0.002095) - expandDecimals(5, 12) + GAS_BUFFER.DEPOSIT ); expect(await usdc.balanceOf(multichainVault.address)).eq(0); expect(await wnt.balanceOf(depositVault.address)).eq(0); diff --git a/test/multichain/MultichainLifeCycle.ts b/test/multichain/MultichainLifeCycle.ts index a438e0d2b..3de4c3992 100644 --- a/test/multichain/MultichainLifeCycle.ts +++ b/test/multichain/MultichainLifeCycle.ts @@ -17,6 +17,7 @@ import { getBalanceOf } from "../../utils/token"; import { bridgeInTokens } from "../../utils/multichain"; import { executeGlvDeposit } from "../../utils/glv/glvDeposit"; import { executeGlvWithdrawal } from "../../utils/glv/glvWithdrawal"; +import { GAS_BUFFER } from "../../utils/gas"; describe("MultichainLifeCycle", () => { let fixture; @@ -181,7 +182,7 @@ describe("MultichainLifeCycle", () => { expect(await usdc.balanceOf(multichainVault.address)).eq(0); expect(await wnt.balanceOf(multichainVault.address)).to.approximately( "2095383984763072", // ~0.0021 ETH --> execution fee refunds (from deposit) - expandDecimals(1, 12) + GAS_BUFFER.DEPOSIT ); expect(await getBalanceOf(ethUsdMarket.marketToken, multichainVault.address)).eq(expandDecimals(95_000, 18)); // 95,000 GM expect(await wnt.balanceOf(ethUsdMarket.marketToken)).eq(wntAmount); @@ -189,7 +190,7 @@ describe("MultichainLifeCycle", () => { // user's multichain balance expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).to.approximately( "2095383984763072", - expandDecimals(1, 12) + GAS_BUFFER.DEPOSIT ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).to.eq(0); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, ethUsdMarket.marketToken))).to.eq( @@ -274,7 +275,7 @@ describe("MultichainLifeCycle", () => { // user's multichain assets expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).to.approximately( "5093772976750184", // 0.0051 ETH --> execution fee refunds (from deposit + glvDeposit) - expandDecimals(1, 12) + GAS_BUFFER.CUMULATIVE_ACTIONS ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).to.eq(0); @@ -356,7 +357,7 @@ describe("MultichainLifeCycle", () => { wntAmount .div(2) // 50% of WNT deposited .add("6898295959186368"), // execution fee refunds (from deposit + glvDeposit + glvWithdrawal) - expandDecimals(5, 13) + GAS_BUFFER.CUMULATIVE_ACTIONS ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).eq( usdcAmount.div(2) // 50% of USDC deposited @@ -409,7 +410,7 @@ describe("MultichainLifeCycle", () => { wntAmount .div(2) // 50% of WNT deposited .add("6898295959186368"), // execution fee refunds (from deposit + glvDeposit + glvWithdrawal) - expandDecimals(5, 13) + GAS_BUFFER.CUMULATIVE_ACTIONS ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).eq( expandDecimals(22_500, 6) @@ -430,7 +431,7 @@ describe("MultichainLifeCycle", () => { wntAmount .div(2) // 50% of WNT deposited .add("6898295959186368"), // execution fee refunds (from deposit + glvDeposit + glvWithdrawal) - expandDecimals(5, 13) + GAS_BUFFER.CUMULATIVE_ACTIONS ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).to.eq( expandDecimals(22_500, 6) @@ -452,7 +453,7 @@ describe("MultichainLifeCycle", () => { expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).to.approximately( wntAmount // 100% of WNT deposited .add("9383301947066416"), // execution fee refunds (from deposit + glvDeposit + glvWithdrawal + withdrawal) - expandDecimals(5, 13) + GAS_BUFFER.CUMULATIVE_ACTIONS ); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).to.eq( expandDecimals(45_000, 6) diff --git a/test/multichain/MultichainOrderRouter.ts b/test/multichain/MultichainOrderRouter.ts index 73c056f29..2e037816d 100644 --- a/test/multichain/MultichainOrderRouter.ts +++ b/test/multichain/MultichainOrderRouter.ts @@ -29,6 +29,7 @@ import { bridgeInTokens } from "../../utils/multichain"; import { errorsContract } from "../../utils/error"; import { getRelayParams } from "../../utils/relay/helpers"; import { getCreateOrderSignature } from "../../utils/relay/signatures"; +import { GAS_BUFFER } from "../../utils/gas"; describe("MultichainOrderRouter", () => { let fixture; @@ -182,7 +183,7 @@ describe("MultichainOrderRouter", () => { // execution fee is ~0.002113 ETH and the excess is returned to user's multichain balance expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).closeTo( "1922883983383072", - expandDecimals(1, 12) + GAS_BUFFER.ORDER ); // 0.004 - ~0.0021 = ~0.0019 ETH }); @@ -229,7 +230,7 @@ describe("MultichainOrderRouter", () => { // execution fee is ~0.002113 ETH and the excess is returned to user's multichain balance expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).closeTo( "1922643983381152", - expandDecimals(1, 12) + GAS_BUFFER.ORDER ); // 0.004 - ~0.0021 = ~0.0019 ETH expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, usdc.address))).to.eq(0); @@ -337,7 +338,7 @@ describe("MultichainOrderRouter", () => { await executeOrder(fixture, { gasUsageLabel: "executeOrder" }); expect(await dataStore.getUint(keys.multichainBalanceKey(user1.address, wnt.address))).closeTo( "1922883983383072", - expandDecimals(1, 12) + GAS_BUFFER.ORDER ); // ~ 0.0019 ETH }); diff --git a/test/position/Hedge.ts b/test/position/Hedge.ts index ee66d5239..e2fd39737 100644 --- a/test/position/Hedge.ts +++ b/test/position/Hedge.ts @@ -1,17 +1,10 @@ -import { contractAt, deployContract } from "../../utils/deploy"; +import { contractAt } from "../../utils/deploy"; import { deployFixture } from "../../utils/fixture"; -import { grantRole } from "../../utils/role"; -import { validateStoreUtils } from "../../utils/storeUtils"; -import { - getPositionCount, - getPositionKeys, - getAccountPositionCount, - getAccountPositionKeys, -} from "../../utils/position"; +import { getPositionKeys } from "../../utils/position"; import { handleDeposit } from "../../utils/deposit"; -import { applyFactor, bigNumberify, decimalToFloat, expandDecimals } from "../../utils/math"; -import { getOrderKeys, handleOrder, OrderType } from "../../utils/order"; +import { decimalToFloat, expandDecimals } from "../../utils/math"; +import { handleOrder, OrderType } from "../../utils/order"; import * as keys from "../../utils/keys"; import { expect } from "chai"; import { scenes } from "../scenes"; @@ -26,7 +19,7 @@ import { constants } from "ethers"; // eslint-disable-next-line no-undef describe("Hedge GM", () => { let fixture; - let dataStore, exchangeRouter, reader, referralStorage, ethUsdMarket, wnt, usdc; + let dataStore, reader, referralStorage, ethUsdMarket, wnt, usdc; let user0, user1; const highPrices = { @@ -61,7 +54,7 @@ describe("Hedge GM", () => { beforeEach(async () => { fixture = await deployFixture(); - ({ dataStore, reader, exchangeRouter, referralStorage, ethUsdMarket, wnt, usdc } = fixture.contracts); + ({ dataStore, reader, referralStorage, ethUsdMarket, wnt, usdc } = fixture.contracts); ({ user0, user1 } = fixture.accounts); await dataStore.setUint(keys.positionImpactFactorKey(ethUsdMarket.marketToken, true), decimalToFloat(5, 9)); @@ -90,7 +83,7 @@ describe("Hedge GM", () => { await usingResult( getMarketTokenPriceWithPoolValue(fixture, { prices: prices.ethUsdMarket }), - ([marketTokenPrice, poolValueInfo]) => { + ([, poolValueInfo]) => { expect(poolValueInfo.poolValue).eq(expandDecimals(5_000_000, 30)); } ); @@ -216,7 +209,7 @@ describe("Hedge GM", () => { const PIPool = await dataStore.getUint(keys.positionImpactPoolAmountKey(market.marketToken)); console.log(`\n\nPI pool: ${PIPool.toString()}`); - const [marketTokenPrice, poolValueInfo] = await getMarketTokenPriceWithPoolValue(fixture, { + const [, poolValueInfo] = await getMarketTokenPriceWithPoolValue(fixture, { prices, market: market, }); @@ -372,7 +365,7 @@ describe("Hedge GM", () => { }); // eslint-disable-next-line no-undef - xit("calc hedge amount for a single asset deposit", async () => { + it("calc hedge amount for a single asset deposit", async () => { // User mints GM tokens for a $550k worth @ $5500 /ETH // deposit in a single asset const userEthBalance = await wnt.balanceOf(user1.address); diff --git a/utils/gas.ts b/utils/gas.ts index 1ba68527a..076b13e80 100644 --- a/utils/gas.ts +++ b/utils/gas.ts @@ -1,4 +1,5 @@ import { TransactionReceipt } from "@ethersproject/providers"; +import { expandDecimals } from "./math"; export async function printGasUsage(provider, txn, label) { const { gasUsed } = await provider.getTransactionReceipt(txn.hash); @@ -17,3 +18,15 @@ export async function logGasUsage({ tx, label }): Promise { return txReceipt; } + +// Gas cost tolerance buffers in wei +// These represent acceptable variation in gas refunds for different operation types +// Increase these values if contract changes cause gas-related test failures +export const GAS_BUFFER = { + DEPOSIT: expandDecimals(5, 12), // 5k gwei = 0.000005 ETH + GLV_DEPOSIT: expandDecimals(5, 12), // 5k gwei = 0.000005 ETH + WITHDRAWAL: expandDecimals(5, 12), // 5k gwei = 0.000005 ETH + GLV_WITHDRAWAL: expandDecimals(5, 12), // 5k gwei = 0.000005 ETH + ORDER: expandDecimals(20, 12), // 20k gwei = 0.00002 ETH + CUMULATIVE_ACTIONS: expandDecimals(50, 12), // 50k gwei = 0.00005 ETH e.g. deposit + glvDeposit + withdrawal + glvWithdrawal +}; diff --git a/utils/keys.ts b/utils/keys.ts index a28c5a8be..c130e2696 100644 --- a/utils/keys.ts +++ b/utils/keys.ts @@ -148,6 +148,7 @@ export const COLLATERAL_SUM = hashString("COLLATERAL_SUM"); export const POOL_AMOUNT = hashString("POOL_AMOUNT"); export const MAX_POOL_AMOUNT = hashString("MAX_POOL_AMOUNT"); export const MAX_POOL_USD_FOR_DEPOSIT = hashString("MAX_POOL_USD_FOR_DEPOSIT"); +export const MAX_COLLATERAL_SUM = hashString("MAX_COLLATERAL_SUM"); export const MAX_OPEN_INTEREST = hashString("MAX_OPEN_INTEREST"); export const POSITION_IMPACT_POOL_AMOUNT = hashString("POSITION_IMPACT_POOL_AMOUNT"); @@ -220,6 +221,7 @@ export const BORROWING_FACTOR = hashString("BORROWING_FACTOR"); export const BORROWING_EXPONENT_FACTOR = hashString("BORROWING_EXPONENT_FACTOR"); export const SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = hashString("SKIP_BORROWING_FEE_FOR_SMALLER_SIDE"); +export const USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE = hashString("USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE"); export const ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = hashString("ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1"); export const ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = hashString("ESTIMATED_GAS_FEE_PER_ORACLE_PRICE"); @@ -337,6 +339,8 @@ export const FEE_DISTRIBUTOR_V1_FEES_WNT_FACTOR = hashString("FEE_DISTRIBUTOR_V1 export const FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR = hashString("FEE_DISTRIBUTOR_V2_FEES_WNT_FACTOR"); export const CONTRIBUTOR_LAST_PAYMENT_AT = hashString("CONTRIBUTOR_LAST_PAYMENT_AT"); +export const CONTRIBUTOR_ACCOUNT_LIST = hashString("CONTRIBUTOR_ACCOUNT_LIST"); +export const CONTRIBUTOR_TOKEN_AMOUNT = hashString("CONTRIBUTOR_TOKEN_AMOUNT"); export function accountDepositListKey(account) { return hashData(["bytes32", "address"], [ACCOUNT_DEPOSIT_LIST, account]); @@ -1009,3 +1013,7 @@ export function feeDistributorAddressInfoKey(chainId: number, addressName: strin export function feeDistributorAddressInfoForChainKey(chainId: number, addressName: string) { return hashData(["bytes32", "uint256", "bytes32"], [FEE_DISTRIBUTOR_ADDRESS_INFO_FOR_CHAIN, chainId, addressName]); } + +export function contributorTokenAmountKey(account: string, token: string) { + return hashData(["bytes32", "address", "address"], [CONTRIBUTOR_TOKEN_AMOUNT, account, token]); +} diff --git a/utils/multichain.ts b/utils/multichain.ts index 9090d3e9a..810bac3e0 100644 --- a/utils/multichain.ts +++ b/utils/multichain.ts @@ -22,6 +22,7 @@ export async function bridgeInTokens( amount: BigNumberish; data?: string; stargatePool?: Contract; + nativeTopUpAmount?: BigNumberish; } ) { const { layerZeroProvider, mockStargatePoolUsdc, mockStargatePoolNative } = fixture.contracts; @@ -31,7 +32,11 @@ export async function bridgeInTokens( const token = overrides.token; const amount = overrides.amount; const stargatePool = overrides.stargatePool || token ? mockStargatePoolUsdc : mockStargatePoolNative; - const msgValue = token ? 0 : amount; // if token is provided, we don't send native token + let msgValue = token ? 0 : amount; // if token is provided, we don't send native token + + if (overrides.nativeTopUpAmount) { + msgValue = ethers.BigNumber.from(msgValue).add(overrides.nativeTopUpAmount); + } if (token) { // e.g. StargatePoolUsdc is being used to bridge USDC @@ -39,6 +44,13 @@ export async function bridgeInTokens( await token.connect(account).approve(stargatePool.address, amount); } + if (!overrides.data && overrides.nativeTopUpAmount) { + overrides.data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [0 /* ActionType.None */, overrides.nativeTopUpAmount, "0x"] + ); + } + // mock token bridging (increase user's multichain balance) const encodedMessageEth = ethers.utils.defaultAbiCoder.encode( ["address", "bytes"], @@ -163,7 +175,8 @@ const createGlvWithdrawalParamsType = `tuple( export async function encodeDepositMessage( depositParams: Parameters[0], - account: string + account: string, + expectedNativeValue: BigNumberish = 0 ): Promise { const relayParams = await getRelayParams(depositParams); @@ -179,7 +192,10 @@ export async function encodeDepositMessage( ); const ActionType = 1; // Deposit - const data = ethers.utils.defaultAbiCoder.encode(["uint8", "bytes"], [ActionType, actionData]); + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [ActionType, expectedNativeValue, actionData] + ); const message = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); @@ -188,7 +204,8 @@ export async function encodeDepositMessage( export async function encodeWithdrawalMessage( withdrawalParams: Parameters[0], - account: string + account: string, + expectedNativeValue: BigNumberish = 0 ): Promise { const relayParams = await getRelayParams(withdrawalParams); @@ -204,7 +221,10 @@ export async function encodeWithdrawalMessage( ); const ActionType = 5; // Withdrawal - const data = ethers.utils.defaultAbiCoder.encode(["uint8", "bytes"], [ActionType, actionData]); + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [ActionType, expectedNativeValue, actionData] + ); const message = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); @@ -213,7 +233,8 @@ export async function encodeWithdrawalMessage( export async function encodeGlvDepositMessage( glvDepositParams: Parameters[0], - account: string + account: string, + expectedNativeValue: BigNumberish = 0 ): Promise { const relayParams = await getRelayParams(glvDepositParams); @@ -229,7 +250,10 @@ export async function encodeGlvDepositMessage( ); const ActionType = 2; // GlvDeposit - const data = ethers.utils.defaultAbiCoder.encode(["uint8", "bytes"], [ActionType, actionData]); + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [ActionType, expectedNativeValue, actionData] + ); const message = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); @@ -238,7 +262,8 @@ export async function encodeGlvDepositMessage( export async function encodeGlvWithdrawalMessage( glvWithdrawalParams: Parameters[0], - account: string + account: string, + expectedNativeValue: BigNumberish = 0 ): Promise { const relayParams = await getRelayParams(glvWithdrawalParams); @@ -254,7 +279,10 @@ export async function encodeGlvWithdrawalMessage( ); const ActionType = 6; // GlvWithdrawal - const data = ethers.utils.defaultAbiCoder.encode(["uint8", "bytes"], [ActionType, actionData]); + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [ActionType, expectedNativeValue, actionData] + ); const message = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); @@ -264,7 +292,8 @@ export async function encodeGlvWithdrawalMessage( export async function encodeSetTraderReferralCodeMessage( setTraderReferralCodeParams: Parameters[0], referralCode: string, - account: string + account: string, + expectedNativeValue: BigNumberish = 0 ): Promise { const relayParams = await getRelayParams(setTraderReferralCodeParams); @@ -280,7 +309,10 @@ export async function encodeSetTraderReferralCodeMessage( ); const ActionType = 4; // SetTraderReferralCode - const data = ethers.utils.defaultAbiCoder.encode(["uint8", "bytes"], [ActionType, actionData]); + const data = ethers.utils.defaultAbiCoder.encode( + ["uint8", "uint256", "bytes"], + [ActionType, expectedNativeValue, actionData] + ); const message = ethers.utils.defaultAbiCoder.encode(["address", "bytes"], [account, data]); diff --git a/utils/prices.ts b/utils/prices.ts index 33c76cf40..cc1618756 100644 --- a/utils/prices.ts +++ b/utils/prices.ts @@ -1,5 +1,5 @@ import fetch from "node-fetch"; -import hre, { ethers } from "hardhat"; +import hre from "hardhat"; import { expandDecimals, bigNumberify } from "./math"; export async function fetchTickerPrices() { diff --git a/yarn.lock b/yarn.lock index ec5e44963..69c1af472 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1698,6 +1698,16 @@ resolved "https://registry.yarnpkg.com/@layerzerolabs/lz-evm-messagelib-v2/-/lz-evm-messagelib-v2-2.0.11.tgz#8437a2a30e9794c56393d83b3f9d2671aadf2648" integrity sha512-i6nZvzxzH+3bMzGRxIzf6fFXTzxQIZ1vyduAoFTy3U2zK9xZUHunKFfpC+vqCY1goNzjBquX4VnClWMWlc5ZIA== +"@layerzerolabs/lz-evm-messagelib-v2@3.0.74": + version "3.0.74" + resolved "https://registry.yarnpkg.com/@layerzerolabs/lz-evm-messagelib-v2/-/lz-evm-messagelib-v2-3.0.74.tgz#63108f0681ec76df30370477452058aacbccda2d" + integrity sha512-bXgnnr6ZZLqf0OSpOkXEpSP/t7sCoI6bheUyP/nZg3GvNutbseTkGXlv46+QG447KovuTURZCBM4NB//bj8hsQ== + +"@layerzerolabs/lz-evm-oapp-v2@3.0.75": + version "3.0.75" + resolved "https://registry.yarnpkg.com/@layerzerolabs/lz-evm-oapp-v2/-/lz-evm-oapp-v2-3.0.75.tgz#e0666cea2bb61ffe113c1e3af9c9c62aa7dbeb77" + integrity sha512-O2B56PVTltUjjTbb8JVVS+l4S9zws9lgi/ufXU5yFwMqwgByRv+PJapBZn359a6dhe9wZpjRaDDbjor7FEth7g== + "@layerzerolabs/lz-evm-oapp-v2@~2.3.25": version "2.3.44" resolved "https://registry.yarnpkg.com/@layerzerolabs/lz-evm-oapp-v2/-/lz-evm-oapp-v2-2.3.44.tgz#e6a2e9fc60e7f21009138405cc21e3bcfe48177d" @@ -1782,6 +1792,11 @@ dependencies: ethers "^5.7.2" +"@layerzerolabs/oft-evm@3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@layerzerolabs/oft-evm/-/oft-evm-3.1.2.tgz#599056728ea065038092084ba490579f8e88de55" + integrity sha512-2aqbnZW8SuLzhSBpQEraEl4LJYi97oNqxg5GTWoIvQNebQ/qkbppEs6kaEQxFqgo+I78v6Vu3SB7XIwpvG7K/w== + "@ledgerhq/connect-kit-loader@^1.1.0": version "1.1.2" resolved "https://registry.yarnpkg.com/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.1.2.tgz#d550e3c1f046e4c796f32a75324b03606b7e226a" @@ -12649,6 +12664,11 @@ solidity-ast@^0.4.60: resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.61.tgz#b51720ece553a2c7d84551ee5a7a2306080d23d0" integrity sha512-OYBJYcYyG7gLV0VuXl9CUrvgJXjV/v0XnR4+1YomVe3q+QyENQXJJxAEASUz4vN6lMAl+C8RSRSr5MBAz09f6w== +solidity-bytes-utils@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/solidity-bytes-utils/-/solidity-bytes-utils-0.8.3.tgz#e509fc41d9a6200395afaae2efd1525bd4cb2d7f" + integrity sha512-sbOHjKF9miqASaqYYC1vvxNnBrzA/wuFPQlOle7rZOSkDiFmCd5x8wQfx2vN95tNGfy8Cf1e5QumW8ZwcByBuQ== + solidity-code-metrics@^0.0.22: version "0.0.22" resolved "https://registry.npmjs.org/solidity-code-metrics/-/solidity-code-metrics-0.0.22.tgz" @@ -15043,4 +15063,4 @@ zustand@^4.3.1: resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.6.tgz#03c78e3e2686c47095c93714c0c600b72a6512bd" integrity sha512-Rb16eW55gqL4W2XZpJh0fnrATxYEG3Apl2gfHTyDSE965x/zxslTikpNch0JgNjJA9zK6gEFW8Fl6d1rTZaqgg== dependencies: - use-sync-external-store "1.2.0" \ No newline at end of file + use-sync-external-store "1.2.0"